From 6b71b52fde2bc496ee84c87b79a4a186e8f78774 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Tue, 4 Sep 2018 16:08:00 +0200 Subject: [PATCH] SONAR-11212 Distinguish predefined and ad hoc external rules --- .../ComputeEngineContainerImplTest.java | 2 +- .../org/sonar/db/version/schema-h2.ddl | 3 +- .../org/sonar/db/rule/RuleDefinitionDto.java | 27 +- .../main/java/org/sonar/db/rule/RuleDto.java | 12 +- .../org/sonar/db/rule/RuleMapper.xml | 4 + .../java/org/sonar/db/rule/RuleDaoTest.java | 367 ++++++++---------- .../java/org/sonar/db/rule/RuleTesting.java | 2 + .../RuleDaoTest/insert_parameter-result.xml | 27 -- .../db/rule/RuleDaoTest/insert_parameter.xml | 22 -- .../db/rule/RuleDaoTest/selectEnabled.xml | 37 -- .../db/rule/RuleDaoTest/selectNonManual.xml | 26 -- .../select_parameters_by_rule_key.xml | 37 -- .../org/sonar/db/rule/RuleDaoTest/shared.xml | 51 --- .../org/sonar/db/rule/RuleDaoTest/update.xml | 18 - .../RuleDaoTest/update_parameter-result.xml | 19 - .../db/rule/RuleDaoTest/update_parameter.xml | 19 - .../MigrationConfigurationModule.java | 2 + .../version/v74/AddIsAdHocToRules.java | 47 +++ .../db/migration/version/v74/DbVersion74.java | 36 ++ .../version/v74/PopulateIsAdHocOnRules.java | 54 +++ ...PopulateNullValuesOfIsExternalOnRules.java | 54 +++ ...sExternalAndIsAdHocNotNullableInRules.java | 50 +++ .../migration/version/v74/package-info.java | 24 ++ .../MigrationConfigurationModuleTest.java | 2 +- .../version/v74/AddIsAdHocToRulesTest.java | 55 +++ .../version/v74/DbVersion74Test.java | 40 ++ .../v74/PopulateIsAdHocOnRulesTest.java | 120 ++++++ ...lateNullValuesOfIsExternalOnRulesTest.java | 105 +++++ ...ernalAndIsAdHocNotNullableInRulesTest.java | 54 +++ .../v74/AddIsAdHocToRulesTest/rules.sql | 27 ++ .../v74/PopulateIsAdHocOnRulesTest/rules.sql | 28 ++ .../rules.sql | 27 ++ .../rules.sql | 28 ++ .../server/rule/ExternalRuleCreatorTest.java | 1 + .../extract_directory_path.xml | 5 +- .../extract_file_path.xml | 5 +- .../many_projects.xml | 5 +- .../IssueIteratorFactoryTest/one_issue.xml | 5 +- .../index/IssueIteratorFactoryTest/shared.xml | 5 +- .../org/sonar/server/rule/RegisterRules.java | 7 +- .../org/sonar/server/rule/RuleCreator.java | 2 + .../sonar/server/batch/IssuesActionTest.java | 2 +- .../sonar/server/rule/RegisterRulesTest.java | 222 ++++++----- .../sonar/server/rule/RuleCreatorTest.java | 2 + .../platform/BackendCleanupTest/shared.xml | 2 + 45 files changed, 1135 insertions(+), 554 deletions(-) delete mode 100644 server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_parameter-result.xml delete mode 100644 server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_parameter.xml delete mode 100644 server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectEnabled.xml delete mode 100644 server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectNonManual.xml delete mode 100644 server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_parameters_by_rule_key.xml delete mode 100644 server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/shared.xml delete mode 100644 server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update.xml delete mode 100644 server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter-result.xml delete mode 100644 server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter.xml create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddIsAdHocToRules.java create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74.java create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateIsAdHocOnRules.java create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateNullValuesOfIsExternalOnRules.java create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/SetIsExternalAndIsAdHocNotNullableInRules.java create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/package-info.java create mode 100644 server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/AddIsAdHocToRulesTest.java create mode 100644 server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74Test.java create mode 100644 server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/PopulateIsAdHocOnRulesTest.java create mode 100644 server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/PopulateNullValuesOfIsExternalOnRulesTest.java create mode 100644 server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/SetIsExternalAndIsAdHocNotNullableInRulesTest.java create mode 100644 server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/AddIsAdHocToRulesTest/rules.sql create mode 100644 server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/PopulateIsAdHocOnRulesTest/rules.sql create mode 100644 server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/PopulateNullValuesOfIsExternalOnRulesTest/rules.sql create mode 100644 server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/SetIsExternalAndIsAdHocNotNullableInRulesTest/rules.sql diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java index 81fe42adca6..369ef9a8578 100644 --- a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java +++ b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java @@ -115,7 +115,7 @@ public class ComputeEngineContainerImplTest { ); assertThat(picoContainer.getParent().getParent().getComponentAdapters()).hasSize( CONTAINER_ITSELF - + 17 // MigrationConfigurationModule + + 18 // MigrationConfigurationModule + 17 // level 2 ); assertThat(picoContainer.getParent().getParent().getParent().getComponentAdapters()).hasSize( 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 4e43f0178e4..db1b8dfd211 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 @@ -201,7 +201,8 @@ CREATE TABLE "RULES" ( "DESCRIPTION_FORMAT" VARCHAR(20), "PRIORITY" INTEGER, "IS_TEMPLATE" BOOLEAN DEFAULT FALSE, - "IS_EXTERNAL" BOOLEAN, + "IS_EXTERNAL" BOOLEAN NOT NULL, + "IS_AD_HOC" BOOLEAN NOT NULL, "TEMPLATE_ID" INTEGER, "PLUGIN_CONFIG_KEY" VARCHAR(200), "NAME" VARCHAR(200), 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 9eeaccf681a..4d96f20ae23 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 @@ -47,7 +47,19 @@ public class RuleDefinitionDto { private String configKey; private Integer severity; private boolean isTemplate; + + /** + * This flag specify that this is an external rule, meaning that generated issues from this rule will be provided by the analyzer without being activated on a quality profile. + */ private boolean isExternal; + + /** + * When an external rule is defined as ad hoc, it means that it's not defined using {@link org.sonar.api.server.rule.RulesDefinition.Context#createExternalRepository(String, String)}. + * As the opposite, an external rule not being defined as ad hoc is declared by using {@link org.sonar.api.server.rule.RulesDefinition.Context#createExternalRepository(String, String)}. + * This flag is only used for external rules (it can only be set to true for when {@link #isExternal()} is true) + */ + private boolean isAdHoc; + private String language; private Integer templateId; private String defRemediationFunction; @@ -73,8 +85,11 @@ public class RuleDefinitionDto { return key; } - void setKey(RuleKey key) { + RuleDefinitionDto setKey(RuleKey key) { this.key = key; + setRepositoryKey(key.repository()); + setRuleKey(key.rule()); + return this; } public Integer getId() { @@ -187,7 +202,6 @@ public class RuleDefinitionDto { return this; } - public boolean isExternal() { return isExternal; } @@ -197,6 +211,15 @@ public class RuleDefinitionDto { return this; } + public boolean isAdHoc() { + return isAdHoc; + } + + public RuleDefinitionDto setIsAdHoc(boolean isAdHoc) { + this.isAdHoc = isAdHoc; + return this; + } + @CheckForNull public String getLanguage() { return language; 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 6fe07bcfb6e..843c5733b66 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 @@ -59,9 +59,6 @@ public class RuleDto { } public RuleKey getKey() { - if (definition.getKey() == null) { - definition.setKey(RuleKey.of(getRepositoryKey(), getRuleKey())); - } return definition.getKey(); } @@ -186,6 +183,15 @@ public class RuleDto { return this; } + public boolean isAdHoc() { + return definition.isAdHoc(); + } + + public RuleDto setIsAdhoc(boolean isAdHoc) { + definition.setIsAdHoc(isAdHoc); + return this; + } + public boolean isTemplate() { return definition.isTemplate(); } 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 12957844f6b..2150cf25df4 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 @@ -15,6 +15,7 @@ r.priority as "severity", r.is_template as "isTemplate", r.is_external as "isExternal", + r.is_ad_hoc as "isAdHoc", r.language as "language", r.template_id as "templateId", r.def_remediation_function as "defRemediationFunction", @@ -300,6 +301,7 @@ priority, is_template, is_external, + is_ad_hoc, language, template_id, def_remediation_function, @@ -325,6 +327,7 @@ #{severity,jdbcType=INTEGER}, #{isTemplate,jdbcType=BOOLEAN}, #{isExternal,jdbcType=BOOLEAN}, + #{isAdHoc,jdbcType=BOOLEAN}, #{language,jdbcType=VARCHAR}, #{templateId,jdbcType=INTEGER}, #{defRemediationFunction,jdbcType=VARCHAR}, @@ -353,6 +356,7 @@ priority=#{severity,jdbcType=INTEGER}, is_template=#{isTemplate,jdbcType=BOOLEAN}, is_external=#{isExternal,jdbcType=BOOLEAN}, + is_ad_hoc=#{isAdHoc,jdbcType=BOOLEAN}, language=#{language,jdbcType=VARCHAR}, template_id=#{templateId,jdbcType=INTEGER}, def_remediation_function=#{defRemediationFunction,jdbcType=VARCHAR}, 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 8020ec57663..399dda82f17 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 @@ -19,7 +19,6 @@ */ package org.sonar.db.rule; -import com.google.common.collect.Iterables; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -49,7 +48,6 @@ 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.ImmutableSet.of; import static com.google.common.collect.Sets.newHashSet; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; @@ -57,10 +55,13 @@ import static java.util.Collections.singletonList; import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; +import static org.sonar.api.rule.RuleStatus.REMOVED; +import static org.sonar.db.rule.RuleTesting.newRuleMetadata; public class RuleDaoTest { private static final String ORGANIZATION_UUID = "org-1"; + private static final int UNKNOWN_RULE_ID = 1_234_567_890; @Rule public ExpectedException thrown = ExpectedException.none(); @@ -79,7 +80,7 @@ public class RuleDaoTest { public void selectByKey() { RuleDefinitionDto ruleDefinition = db.rules().insert(); OrganizationDto organization = db.organizations().insert(); - RuleMetadataDto metadata = newRuleMetadata(organization, "1"); + RuleMetadataDto metadata = newRuleMetadata(ruleDefinition, organization); db.rules().insertRule(ruleDefinition, metadata); assertThat(underTest.selectByKey(db.getSession(), organization, RuleKey.of("foo", "bar"))) @@ -110,10 +111,10 @@ public class RuleDaoTest { public void selectByKey_returns_metadata_of_specified_organization() { RuleDefinitionDto ruleDefinition = db.rules().insert(); OrganizationDto organization1 = db.organizations().insert(); - RuleMetadataDto expectedOrg1 = newRuleMetadata(organization1, "1"); + RuleMetadataDto expectedOrg1 = newRuleMetadata(ruleDefinition, organization1); db.rules().insertRule(ruleDefinition, expectedOrg1); OrganizationDto organization2 = db.organizations().insert(); - RuleMetadataDto expectedOrg2 = newRuleMetadata(organization2, "2"); + RuleMetadataDto expectedOrg2 = newRuleMetadata(ruleDefinition, organization2); db.rules().insertRule(ruleDefinition, expectedOrg2); RuleDto rule = underTest.selectByKey(db.getSession(), organization1, ruleDefinition.getKey()).get(); @@ -124,20 +125,19 @@ public class RuleDaoTest { @Test public void selectDefinitionByKey() { - db.prepareDbUnit(getClass(), "shared.xml"); + RuleDefinitionDto rule = db.rules().insert(); assertThat(underTest.selectDefinitionByKey(db.getSession(), RuleKey.of("NOT", "FOUND")).isPresent()).isFalse(); - Optional rule = underTest.selectDefinitionByKey(db.getSession(), RuleKey.of("java", "S001")); - assertThat(rule.isPresent()).isTrue(); - assertThat(rule.get().getId()).isEqualTo(1); + Optional reloaded = underTest.selectDefinitionByKey(db.getSession(), rule.getKey()); + assertThat(reloaded.isPresent()).isTrue(); } @Test public void selectById() { RuleDefinitionDto ruleDefinition = db.rules().insert(); OrganizationDto organization = db.organizations().insert(); - RuleMetadataDto metadata = newRuleMetadata(organization, "1"); + RuleMetadataDto metadata = newRuleMetadata(ruleDefinition, organization); RuleDto expected = db.rules().insertRule(ruleDefinition, metadata); assertThat(underTest.selectById(expected.getId() + 500, organization.getUuid(), db.getSession())) @@ -168,10 +168,10 @@ public class RuleDaoTest { public void selectById_returns_metadata_of_specified_organization() { RuleDefinitionDto ruleDefinition = db.rules().insert(); OrganizationDto organization1 = db.organizations().insert(); - RuleMetadataDto expectedOrg1 = newRuleMetadata(organization1, "1"); + RuleMetadataDto expectedOrg1 = newRuleMetadata(ruleDefinition, organization1); db.rules().insertRule(ruleDefinition, expectedOrg1); OrganizationDto organization2 = db.organizations().insert(); - RuleMetadataDto expectedOrg2 = newRuleMetadata(organization2, "2"); + RuleMetadataDto expectedOrg2 = newRuleMetadata(ruleDefinition, organization2); db.rules().insertRule(ruleDefinition, expectedOrg2); RuleDto rule = underTest.selectById(ruleDefinition.getId(), organization1.getUuid(), db.getSession()).get(); @@ -182,81 +182,84 @@ public class RuleDaoTest { @Test public void selectDefinitionById() { - db.prepareDbUnit(getClass(), "shared.xml"); + RuleDefinitionDto rule = db.rules().insert(); - assertThat(underTest.selectDefinitionById(55l, db.getSession())).isEmpty(); - Optional ruleDtoOptional = underTest.selectDefinitionById(1l, db.getSession()); + assertThat(underTest.selectDefinitionById(1_234_567L, db.getSession())).isEmpty(); + Optional ruleDtoOptional = underTest.selectDefinitionById(rule.getId(), db.getSession()); assertThat(ruleDtoOptional).isPresent(); - assertThat(ruleDtoOptional.get().getId()).isEqualTo(1); } @Test public void selectByIds() { - db.prepareDbUnit(getClass(), "shared.xml"); - String organizationUuid = "org-1"; - - assertThat(underTest.selectByIds(db.getSession(), organizationUuid, asList(1))).hasSize(1); - assertThat(underTest.selectByIds(db.getSession(), organizationUuid, asList(1, 2))).hasSize(2); - assertThat(underTest.selectByIds(db.getSession(), organizationUuid, asList(1, 2, 3))).hasSize(2); - - assertThat(underTest.selectByIds(db.getSession(), organizationUuid, asList(123))).isEmpty(); + OrganizationDto organization = db.organizations().insert(); + RuleDefinitionDto rule1 = db.rules().insert(); + db.rules().insertOrUpdateMetadata(rule1, organization); + RuleDefinitionDto rule2 = db.rules().insert(); + db.rules().insertOrUpdateMetadata(rule2, organization); + RuleDefinitionDto removedRule = db.rules().insert(r -> r.setStatus(REMOVED)); + db.rules().insertOrUpdateMetadata(removedRule, organization); + + assertThat(underTest.selectByIds(db.getSession(), organization.getUuid(), singletonList(rule1.getId()))).hasSize(1); + assertThat(underTest.selectByIds(db.getSession(), organization.getUuid(), asList(rule1.getId(), rule2.getId()))).hasSize(2); + assertThat(underTest.selectByIds(db.getSession(), organization.getUuid(), asList(rule1.getId(), rule2.getId(), UNKNOWN_RULE_ID))).hasSize(2); + assertThat(underTest.selectByIds(db.getSession(), organization.getUuid(), asList(rule1.getId(), rule2.getId(), removedRule.getId()))).hasSize(3); + assertThat(underTest.selectByIds(db.getSession(), organization.getUuid(), singletonList(UNKNOWN_RULE_ID))).isEmpty(); } @Test public void selectByIds_populates_organizationUuid_even_when_organization_has_no_metadata() { - db.prepareDbUnit(getClass(), "shared.xml"); - String organizationUuid = "org-1"; + OrganizationDto organization = db.organizations().insert(); + RuleDefinitionDto rule1 = db.rules().insert(); + RuleDefinitionDto rule2 = db.rules().insert(); - assertThat(underTest.selectByIds(db.getSession(), organizationUuid, asList(1, 2))) + assertThat(underTest.selectByIds(db.getSession(), organization.getUuid(), asList(rule1.getId(), rule2.getId()))) .extracting(RuleDto::getOrganizationUuid) - .containsExactly(organizationUuid, organizationUuid); + .containsExactly(organization.getUuid(), organization.getUuid()); } @Test public void selectDefinitionByIds() { - db.prepareDbUnit(getClass(), "shared.xml"); + RuleDefinitionDto rule1 = db.rules().insert(); + RuleDefinitionDto rule2 = db.rules().insert(); - assertThat(underTest.selectDefinitionByIds(db.getSession(), asList(1))).hasSize(1); - assertThat(underTest.selectDefinitionByIds(db.getSession(), asList(1, 2))).hasSize(2); - assertThat(underTest.selectDefinitionByIds(db.getSession(), asList(1, 2, 3))).hasSize(2); + assertThat(underTest.selectDefinitionByIds(db.getSession(), singletonList(rule1.getId()))).hasSize(1); + assertThat(underTest.selectDefinitionByIds(db.getSession(), asList(rule1.getId(), rule2.getId()))).hasSize(2); + assertThat(underTest.selectDefinitionByIds(db.getSession(), asList(rule1.getId(), rule2.getId(), UNKNOWN_RULE_ID))).hasSize(2); - assertThat(underTest.selectDefinitionByIds(db.getSession(), asList(123))).isEmpty(); + assertThat(underTest.selectDefinitionByIds(db.getSession(), singletonList(UNKNOWN_RULE_ID))).isEmpty(); } @Test public void selectOrFailByKey() { - db.prepareDbUnit(getClass(), "shared.xml"); + OrganizationDto organization = db.organizations().insert(); + RuleDefinitionDto rule1 = db.rules().insert(); + RuleDefinitionDto rule2 = db.rules().insert(); - OrganizationDto organization = OrganizationTesting.newOrganizationDto().setUuid("org-1"); - RuleDto rule = underTest.selectOrFailByKey(db.getSession(), organization, RuleKey.of("java", "S001")); - assertThat(rule.getId()).isEqualTo(1); + RuleDto rule = underTest.selectOrFailByKey(db.getSession(), organization, rule1.getKey()); + assertThat(rule.getId()).isEqualTo(rule1.getId()); } @Test public void selectOrFailByKey_fails_if_rule_not_found() { - db.prepareDbUnit(getClass(), "shared.xml"); + OrganizationDto organization = db.organizations().insert(); thrown.expect(RowNotFoundException.class); thrown.expectMessage("Rule with key 'NOT:FOUND' does not exist"); - OrganizationDto organization = OrganizationTesting.newOrganizationDto().setUuid("org-1"); underTest.selectOrFailByKey(db.getSession(), organization, RuleKey.of("NOT", "FOUND")); } @Test public void selectOrFailByKey_populates_organizationUuid_even_when_organization_has_no_metadata() { - db.prepareDbUnit(getClass(), "shared.xml"); - String organizationUuid = "org-1"; + OrganizationDto organization = db.organizations().insert(); + RuleDefinitionDto rule = db.rules().insert(); - OrganizationDto organization = OrganizationTesting.newOrganizationDto().setUuid(organizationUuid); - assertThat(underTest.selectOrFailByKey(db.getSession(), organization, RuleKey.of("java", "S001")).getOrganizationUuid()) - .isEqualTo(organizationUuid); + assertThat(underTest.selectOrFailByKey(db.getSession(), organization, rule.getKey()).getOrganizationUuid()) + .isEqualTo(organization.getUuid()); } @Test public void selectOrFailDefinitionByKey_fails_if_rule_not_found() { - db.prepareDbUnit(getClass(), "shared.xml"); - thrown.expect(RowNotFoundException.class); thrown.expectMessage("Rule with key 'NOT:FOUND' does not exist"); @@ -265,37 +268,40 @@ public class RuleDaoTest { @Test public void selectByKeys() { - db.prepareDbUnit(getClass(), "shared.xml"); - String organizationUuid = "org-1"; + OrganizationDto organization = db.organizations().insert(); + RuleDefinitionDto rule1 = db.rules().insert(); + db.rules().insertOrUpdateMetadata(rule1, organization); + RuleDefinitionDto rule2 = db.rules().insert(); + db.rules().insertOrUpdateMetadata(rule2, organization); - assertThat(underTest.selectByKeys(db.getSession(), organizationUuid, Collections.emptyList())).isEmpty(); - assertThat(underTest.selectByKeys(db.getSession(), organizationUuid, asList(RuleKey.of("NOT", "FOUND")))).isEmpty(); + assertThat(underTest.selectByKeys(db.getSession(), organization.getUuid(), Collections.emptyList())).isEmpty(); + assertThat(underTest.selectByKeys(db.getSession(), organization.getUuid(), asList(RuleKey.of("NOT", "FOUND")))).isEmpty(); - List rules = underTest.selectByKeys(db.getSession(), organizationUuid, asList(RuleKey.of("java", "S001"), RuleKey.of("java", "OTHER"))); + List rules = underTest.selectByKeys(db.getSession(), organization.getUuid(), asList(rule1.getKey(), RuleKey.of("java", "OTHER"))); assertThat(rules).hasSize(1); - assertThat(rules.get(0).getId()).isEqualTo(1); + assertThat(rules.get(0).getId()).isEqualTo(rule1.getId()); } @Test public void selectByKeys_populates_organizationUuid_even_when_organization_has_no_metadata() { - db.prepareDbUnit(getClass(), "shared.xml"); - String organizationUuid = "org-1"; + OrganizationDto organization = db.organizations().insert(); + RuleDefinitionDto rule = db.rules().insert(); - assertThat(underTest.selectByKeys(db.getSession(), organizationUuid, asList(RuleKey.of("java", "S001"), RuleKey.of("java", "OTHER")))) + assertThat(underTest.selectByKeys(db.getSession(), organization.getUuid(), singletonList(rule.getKey()))) .extracting(RuleDto::getOrganizationUuid) - .containsExactly(organizationUuid); + .containsExactly(organization.getUuid()); } @Test public void selectDefinitionByKeys() { - db.prepareDbUnit(getClass(), "shared.xml"); + RuleDefinitionDto rule = db.rules().insert(); assertThat(underTest.selectDefinitionByKeys(db.getSession(), Collections.emptyList())).isEmpty(); assertThat(underTest.selectDefinitionByKeys(db.getSession(), asList(RuleKey.of("NOT", "FOUND")))).isEmpty(); - List rules = underTest.selectDefinitionByKeys(db.getSession(), asList(RuleKey.of("java", "S001"), RuleKey.of("java", "OTHER"))); + List rules = underTest.selectDefinitionByKeys(db.getSession(), asList(rule.getKey(), RuleKey.of("java", "OTHER"))); assertThat(rules).hasSize(1); - assertThat(rules.get(0).getId()).isEqualTo(1); + assertThat(rules.get(0).getId()).isEqualTo(rule.getId()); } @Test @@ -340,7 +346,7 @@ public class RuleDaoTest { public void selectAll_returns_metadata_of_specified_organization() { RuleDefinitionDto ruleDefinition = db.rules().insert(); OrganizationDto organization = db.organizations().insert(); - RuleMetadataDto expected = newRuleMetadata(organization, "1"); + RuleMetadataDto expected = newRuleMetadata(ruleDefinition, organization); db.rules().insertRule(ruleDefinition, expected); List rules = underTest.selectAll(db.getSession(), organization.getUuid()); @@ -372,8 +378,6 @@ public class RuleDaoTest { assertThat(actual.getSystemTags()).isEqualTo(expected.getSystemTags()); assertThat(actual.getSecurityStandards()).isEqualTo(expected.getSecurityStandards()); assertThat(actual.getType()).isEqualTo(expected.getType()); - assertThat(actual.getCreatedAt()).isEqualTo(expected.getCreatedAt()); - assertThat(actual.getUpdatedAt()).isEqualTo(expected.getUpdatedAt()); } private static void verifyMetadata(RuleMetadataDto metadata, RuleDefinitionDto ruleDefinition, RuleMetadataDto expected) { @@ -385,8 +389,10 @@ public class RuleDaoTest { assertThat(metadata.getNoteData()).isEqualTo(expected.getNoteData()); assertThat(metadata.getNoteCreatedAt()).isEqualTo(expected.getNoteCreatedAt()); assertThat(metadata.getNoteUpdatedAt()).isEqualTo(expected.getNoteUpdatedAt()); - assertThat(metadata.getCreatedAt()).isEqualTo(ruleDefinition.getCreatedAt()); - assertThat(metadata.getUpdatedAt()).isEqualTo(ruleDefinition.getUpdatedAt()); + assertThat(metadata.getAdHocName()).isEqualTo(expected.getAdHocName()); + assertThat(metadata.getAdHocDescription()).isEqualTo(expected.getAdHocDescription()); + assertThat(metadata.getAdHocSeverity()).isEqualTo(expected.getAdHocSeverity()); + assertThat(metadata.getAdHocType()).isEqualTo(expected.getAdHocType()); } private static void verifyNoMetadata(RuleMetadataDto metadata, RuleDefinitionDto ruleDefinition, OrganizationDto organization) { @@ -398,37 +404,27 @@ public class RuleDaoTest { assertThat(metadata.getNoteData()).isNull(); assertThat(metadata.getNoteCreatedAt()).isNull(); assertThat(metadata.getNoteUpdatedAt()).isNull(); - assertThat(metadata.getCreatedAt()).isEqualTo(ruleDefinition.getCreatedAt()); - assertThat(metadata.getUpdatedAt()).isEqualTo(ruleDefinition.getUpdatedAt()); - } - - private static RuleMetadataDto newRuleMetadata(OrganizationDto organization, String seed) { - String noteData = seed + randomAlphanumeric(7); - return new RuleMetadataDto() - .setOrganizationUuid(organization.getUuid()) - .setRemediationBaseEffort(seed + randomAlphanumeric(2)) - .setRemediationFunction(seed + randomAlphanumeric(3)) - .setRemediationGapMultiplier(seed + randomAlphanumeric(4)) - .setTags(of(seed + randomAlphanumeric(5), seed + randomAlphanumeric(6))) - .setNoteData(noteData) - .setNoteCreatedAt(noteData.hashCode() + 50L) - .setNoteUpdatedAt(noteData.hashCode() + 1_999L) - .setCreatedAt(seed.hashCode() + 8889L) - .setUpdatedAt(seed.hashCode() + 10_333L); + assertThat(metadata.getAdHocName()).isNull(); + assertThat(metadata.getAdHocDescription()).isNull(); + assertThat(metadata.getAdHocSeverity()).isNull(); + assertThat(metadata.getAdHocType()).isNull(); } @Test public void selectAllDefinitions() { - db.prepareDbUnit(getClass(), "shared.xml"); + RuleDefinitionDto rule1 = db.rules().insert(); + RuleDefinitionDto rule2 = db.rules().insert(); + RuleDefinitionDto removedRule = db.rules().insert(r -> r.setStatus(REMOVED)); List ruleDtos = underTest.selectAllDefinitions(db.getSession()); - assertThat(ruleDtos).extracting("id").containsOnly(1, 2, 10); + assertThat(ruleDtos).extracting(RuleDefinitionDto::getId).containsOnly(rule1.getId(), rule2.getId(), removedRule.getId()); } @Test public void selectEnabled_with_ResultHandler() { - db.prepareDbUnit(getClass(), "selectEnabled.xml"); + RuleDefinitionDto rule = db.rules().insert(); + RuleDefinitionDto removedRule = db.rules().insert(r -> r.setStatus(REMOVED)); final List rules = new ArrayList<>(); ResultHandler resultHandler = resultContext -> rules.add(resultContext.getResultObject()); @@ -436,39 +432,35 @@ public class RuleDaoTest { assertThat(rules.size()).isEqualTo(1); RuleDefinitionDto ruleDto = rules.get(0); - assertThat(ruleDto.getId()).isEqualTo(1); - assertThat(ruleDto.getName()).isEqualTo("Avoid Null"); - assertThat(ruleDto.getDescription()).isEqualTo("Should avoid NULL"); - assertThat(ruleDto.getDescriptionFormat()).isEqualTo(RuleDto.Format.HTML); - assertThat(ruleDto.getStatus()).isEqualTo(RuleStatus.READY); - assertThat(ruleDto.getRepositoryKey()).isEqualTo("checkstyle"); - assertThat(ruleDto.getDefRemediationFunction()).isEqualTo("LINEAR_OFFSET"); - assertThat(ruleDto.getDefRemediationGapMultiplier()).isEqualTo("5d"); - assertThat(ruleDto.getDefRemediationBaseEffort()).isEqualTo("10h"); - assertThat(ruleDto.getGapDescription()).isEqualTo("squid.S115.effortToFix"); + assertThat(ruleDto.getId()).isEqualTo(rule.getId()); } @Test public void select_by_query() { - db.prepareDbUnit(getClass(), "shared.xml"); - - String organizationUuid = "org-1"; - assertThat(underTest.selectByQuery(db.getSession(), organizationUuid, RuleQuery.create())).hasSize(2); - assertThat(underTest.selectByQuery(db.getSession(), organizationUuid, RuleQuery.create().withKey("S001"))).hasSize(1); - assertThat(underTest.selectByQuery(db.getSession(), organizationUuid, RuleQuery.create().withConfigKey("S1"))).hasSize(1); - assertThat(underTest.selectByQuery(db.getSession(), organizationUuid, RuleQuery.create().withRepositoryKey("java"))).hasSize(2); - assertThat(underTest.selectByQuery(db.getSession(), organizationUuid, + OrganizationDto organization = db.organizations().insert(); + RuleDefinitionDto rule1 = db.rules().insert(r -> r.setKey(RuleKey.of("java", "S001")).setConfigKey("S1")); + db.rules().insertOrUpdateMetadata(rule1, organization); + RuleDefinitionDto rule2 = db.rules().insert(r -> r.setKey(RuleKey.of("java", "S002"))); + db.rules().insertOrUpdateMetadata(rule2, organization); + RuleDefinitionDto removedRule = db.rules().insert(r -> r.setStatus(REMOVED)); + + assertThat(underTest.selectByQuery(db.getSession(), organization.getUuid(), RuleQuery.create())).hasSize(2); + assertThat(underTest.selectByQuery(db.getSession(), organization.getUuid(), RuleQuery.create().withKey("S001"))).hasSize(1); + assertThat(underTest.selectByQuery(db.getSession(), organization.getUuid(), RuleQuery.create().withConfigKey("S1"))).hasSize(1); + assertThat(underTest.selectByQuery(db.getSession(), organization.getUuid(), RuleQuery.create().withRepositoryKey("java"))).hasSize(2); + assertThat(underTest.selectByQuery(db.getSession(), organization.getUuid(), RuleQuery.create().withKey("S001").withConfigKey("S1").withRepositoryKey("java"))).hasSize(1); } @Test public void select_by_query_populates_organizationUuid_even_when_organization_has_no_metadata() { - db.prepareDbUnit(getClass(), "shared.xml"); - String organizationUuid = "org-1"; + OrganizationDto organization = db.organizations().insert(); + RuleDefinitionDto rule1 = db.rules().insert(); + RuleDefinitionDto rule2 = db.rules().insert(); - assertThat(underTest.selectByQuery(db.getSession(), organizationUuid, RuleQuery.create())) + assertThat(underTest.selectByQuery(db.getSession(), organization.getUuid(), RuleQuery.create())) .extracting(RuleDto::getOrganizationUuid) - .containsExactly(organizationUuid, organizationUuid); + .containsExactly(organization.getUuid(), organization.getUuid()); } @Test @@ -484,6 +476,7 @@ public class RuleDaoTest { .setSeverity(Severity.INFO) .setIsTemplate(true) .setIsExternal(true) + .setIsAdHoc(true) .setLanguage("dart") .setTemplateId(3) .setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.toString()) @@ -512,6 +505,7 @@ public class RuleDaoTest { assertThat(ruleDto.getLanguage()).isEqualTo("dart"); assertThat(ruleDto.isTemplate()).isTrue(); assertThat(ruleDto.isExternal()).isTrue(); + assertThat(ruleDto.isAdHoc()).isTrue(); assertThat(ruleDto.getTemplateId()).isEqualTo(3); assertThat(ruleDto.getDefRemediationFunction()).isEqualTo("LINEAR_OFFSET"); assertThat(ruleDto.getDefRemediationGapMultiplier()).isEqualTo("5d"); @@ -527,10 +521,9 @@ public class RuleDaoTest { @Test public void update_RuleDefinitionDto() { - db.prepareDbUnit(getClass(), "update.xml"); - + RuleDefinitionDto rule = db.rules().insert(); RuleDefinitionDto ruleToUpdate = new RuleDefinitionDto() - .setId(1) + .setId(rule.getId()) .setRuleKey("NewRuleKey") .setRepositoryKey("plugin") .setName("new name") @@ -540,6 +533,8 @@ public class RuleDaoTest { .setConfigKey("NewConfigKey") .setSeverity(Severity.INFO) .setIsTemplate(true) + .setIsExternal(true) + .setIsAdHoc(true) .setLanguage("dart") .setTemplateId(3) .setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.toString()) @@ -566,7 +561,8 @@ public class RuleDaoTest { assertThat(ruleDto.getSeverity()).isEqualTo(0); assertThat(ruleDto.getLanguage()).isEqualTo("dart"); assertThat(ruleDto.isTemplate()).isTrue(); - assertThat(ruleDto.isExternal()).isFalse(); + assertThat(ruleDto.isExternal()).isTrue(); + assertThat(ruleDto.isAdHoc()).isTrue(); assertThat(ruleDto.getTemplateId()).isEqualTo(3); assertThat(ruleDto.getDefRemediationFunction()).isEqualTo("LINEAR_OFFSET"); assertThat(ruleDto.getDefRemediationGapMultiplier()).isEqualTo("5d"); @@ -576,17 +572,17 @@ public class RuleDaoTest { assertThat(ruleDto.getSecurityStandards()).containsOnly("owaspTop10:a1", "cwe:123"); assertThat(ruleDto.getScope()).isEqualTo(Scope.ALL); assertThat(ruleDto.getType()).isEqualTo(RuleType.BUG.getDbConstant()); - assertThat(ruleDto.getCreatedAt()).isEqualTo(1_500_000_000_000L); + assertThat(ruleDto.getCreatedAt()).isEqualTo(rule.getCreatedAt()); assertThat(ruleDto.getUpdatedAt()).isEqualTo(2_000_000_000_000L); } @Test public void update_RuleMetadataDto_inserts_row_in_RULE_METADATA_if_not_exists_yet() { - db.prepareDbUnit(getClass(), "update.xml"); + RuleDefinitionDto rule = db.rules().insert(); String organizationUuid = "org-1"; RuleMetadataDto metadataToUpdate = new RuleMetadataDto() - .setRuleId(1) + .setRuleId(rule.getId()) .setOrganizationUuid(organizationUuid) .setNoteData("My note") .setNoteUserUuid("admin") @@ -596,6 +592,10 @@ public class RuleDaoTest { .setRemediationGapMultiplier("1h") .setRemediationBaseEffort("5min") .setTags(newHashSet("tag1", "tag2")) + .setAdHocName("ad hoc name") + .setAdHocDescription("ad hoc desc") + .setAdHocSeverity(Severity.BLOCKER) + .setAdHocType(RuleType.CODE_SMELL) .setCreatedAt(3_500_000_000_000L) .setUpdatedAt(4_000_000_000_000L); @@ -603,49 +603,43 @@ public class RuleDaoTest { db.getSession().commit(); OrganizationDto organization = OrganizationTesting.newOrganizationDto().setUuid(organizationUuid); - RuleDto ruleDto = underTest.selectOrFailByKey(db.getSession(), organization, RuleKey.of("checkstyle", "AvoidNull")); - assertThat(ruleDto.getName()).isEqualTo("Avoid Null"); - assertThat(ruleDto.getDescription()).isEqualTo("Should avoid NULL"); - assertThat(ruleDto.getDescriptionFormat()).isNull(); - assertThat(ruleDto.getStatus()).isEqualTo(RuleStatus.READY); - assertThat(ruleDto.getRuleKey()).isEqualTo("AvoidNull"); - assertThat(ruleDto.getRepositoryKey()).isEqualTo("checkstyle"); - assertThat(ruleDto.getConfigKey()).isEqualTo("AvoidNull"); - assertThat(ruleDto.getSeverity()).isEqualTo(2); - assertThat(ruleDto.getLanguage()).isEqualTo("golo"); - assertThat(ruleDto.isTemplate()).isFalse(); - assertThat(ruleDto.getTemplateId()).isNull(); + RuleDto ruleDto = underTest.selectOrFailByKey(db.getSession(), organization, rule.getKey()); assertThat(ruleDto.getNoteData()).isEqualTo("My note"); assertThat(ruleDto.getNoteUserUuid()).isEqualTo("admin"); assertThat(ruleDto.getNoteCreatedAt()).isNotNull(); assertThat(ruleDto.getNoteUpdatedAt()).isNotNull(); assertThat(ruleDto.getRemediationFunction()).isEqualTo("LINEAR"); - assertThat(ruleDto.getDefRemediationFunction()).isNull(); assertThat(ruleDto.getRemediationGapMultiplier()).isEqualTo("1h"); - assertThat(ruleDto.getDefRemediationGapMultiplier()).isNull(); assertThat(ruleDto.getRemediationBaseEffort()).isEqualTo("5min"); - assertThat(ruleDto.getDefRemediationBaseEffort()).isNull(); - assertThat(ruleDto.getGapDescription()).isNull(); assertThat(ruleDto.getTags()).containsOnly("tag1", "tag2"); - assertThat(ruleDto.getSystemTags()).isEmpty(); + assertThat(ruleDto.getAdHocName()).isEqualTo("ad hoc name"); + assertThat(ruleDto.getAdHocDescription()).isEqualTo("ad hoc desc"); + assertThat(ruleDto.getAdHocSeverity()).isEqualTo(Severity.BLOCKER); + assertThat(ruleDto.getAdHocType()).isEqualTo(RuleType.CODE_SMELL.getDbConstant()); assertThat(ruleDto.getSecurityStandards()).isEmpty(); - assertThat(ruleDto.getType()).isEqualTo(0); assertThat(ruleDto.getCreatedAt()).isEqualTo(3_500_000_000_000L); assertThat(ruleDto.getUpdatedAt()).isEqualTo(4_000_000_000_000L); + // Info from rule definition + assertThat(ruleDto.getDefRemediationFunction()).isEqualTo(rule.getDefRemediationFunction()); + assertThat(ruleDto.getDefRemediationGapMultiplier()).isEqualTo(rule.getDefRemediationGapMultiplier()); + assertThat(ruleDto.getDefRemediationBaseEffort()).isEqualTo(rule.getDefRemediationBaseEffort()); + assertThat(ruleDto.getGapDescription()).isEqualTo(rule.getGapDescription()); + assertThat(ruleDto.getSystemTags()).containsAll(rule.getSystemTags()); + assertThat(ruleDto.getType()).isEqualTo(rule.getType()); } @Test public void update_RuleMetadataDto_updates_row_in_RULE_METADATA_if_already_exists() { - db.prepareDbUnit(getClass(), "update.xml"); + RuleDefinitionDto rule = db.rules().insert(); String organizationUuid = "org-1"; OrganizationDto organization = OrganizationTesting.newOrganizationDto().setUuid(organizationUuid); RuleMetadataDto metadataV1 = new RuleMetadataDto() - .setRuleId(1) + .setRuleId(rule.getId()) .setOrganizationUuid(organizationUuid) .setCreatedAt(3_500_000_000_000L) .setUpdatedAt(4_000_000_000_000L); RuleMetadataDto metadataV2 = new RuleMetadataDto() - .setRuleId(1) + .setRuleId(rule.getId()) .setOrganizationUuid(organizationUuid) .setNoteData("My note") .setNoteUserUuid("admin") @@ -655,6 +649,10 @@ public class RuleDaoTest { .setRemediationGapMultiplier("1h") .setRemediationBaseEffort("5min") .setTags(newHashSet("tag1", "tag2")) + .setAdHocName("ad hoc name") + .setAdHocDescription("ad hoc desc") + .setAdHocSeverity(Severity.BLOCKER) + .setAdHocType(RuleType.CODE_SMELL) .setCreatedAt(6_500_000_000_000L) .setUpdatedAt(7_000_000_000_000L); @@ -662,90 +660,69 @@ public class RuleDaoTest { db.commit(); assertThat(db.countRowsOfTable("RULES_METADATA")).isEqualTo(1); - RuleDto ruleDto = underTest.selectOrFailByKey(db.getSession(), organization, RuleKey.of("checkstyle", "AvoidNull")); - assertThat(ruleDto.getName()).isEqualTo("Avoid Null"); - assertThat(ruleDto.getDescription()).isEqualTo("Should avoid NULL"); - assertThat(ruleDto.getDescriptionFormat()).isNull(); - assertThat(ruleDto.getStatus()).isEqualTo(RuleStatus.READY); - assertThat(ruleDto.getRuleKey()).isEqualTo("AvoidNull"); - assertThat(ruleDto.getRepositoryKey()).isEqualTo("checkstyle"); - assertThat(ruleDto.getConfigKey()).isEqualTo("AvoidNull"); - assertThat(ruleDto.getSeverity()).isEqualTo(2); - assertThat(ruleDto.getLanguage()).isEqualTo("golo"); - assertThat(ruleDto.isTemplate()).isFalse(); - assertThat(ruleDto.getTemplateId()).isNull(); + RuleDto ruleDto = underTest.selectOrFailByKey(db.getSession(), organization, rule.getKey()); assertThat(ruleDto.getNoteData()).isNull(); assertThat(ruleDto.getNoteUserUuid()).isNull(); assertThat(ruleDto.getNoteCreatedAt()).isNull(); assertThat(ruleDto.getNoteUpdatedAt()).isNull(); assertThat(ruleDto.getRemediationFunction()).isNull(); - assertThat(ruleDto.getDefRemediationFunction()).isNull(); assertThat(ruleDto.getRemediationGapMultiplier()).isNull(); - assertThat(ruleDto.getDefRemediationGapMultiplier()).isNull(); assertThat(ruleDto.getRemediationBaseEffort()).isNull(); - assertThat(ruleDto.getDefRemediationBaseEffort()).isNull(); - assertThat(ruleDto.getGapDescription()).isNull(); assertThat(ruleDto.getTags()).isEmpty(); - assertThat(ruleDto.getSystemTags()).isEmpty(); + assertThat(ruleDto.getAdHocName()).isNull(); + assertThat(ruleDto.getAdHocDescription()).isNull(); + assertThat(ruleDto.getAdHocSeverity()).isNull(); + assertThat(ruleDto.getAdHocType()).isNull(); assertThat(ruleDto.getSecurityStandards()).isEmpty(); - assertThat(ruleDto.getType()).isEqualTo(0); assertThat(ruleDto.getCreatedAt()).isEqualTo(3_500_000_000_000L); assertThat(ruleDto.getUpdatedAt()).isEqualTo(4_000_000_000_000L); underTest.insertOrUpdate(db.getSession(), metadataV2); db.commit(); - ruleDto = underTest.selectOrFailByKey(db.getSession(), organization, RuleKey.of("checkstyle", "AvoidNull")); - assertThat(ruleDto.getName()).isEqualTo("Avoid Null"); - assertThat(ruleDto.getDescription()).isEqualTo("Should avoid NULL"); - assertThat(ruleDto.getDescriptionFormat()).isNull(); - assertThat(ruleDto.getStatus()).isEqualTo(RuleStatus.READY); - assertThat(ruleDto.getRuleKey()).isEqualTo("AvoidNull"); - assertThat(ruleDto.getRepositoryKey()).isEqualTo("checkstyle"); - assertThat(ruleDto.getConfigKey()).isEqualTo("AvoidNull"); - assertThat(ruleDto.getSeverity()).isEqualTo(2); - assertThat(ruleDto.getLanguage()).isEqualTo("golo"); - assertThat(ruleDto.isTemplate()).isFalse(); - assertThat(ruleDto.getTemplateId()).isNull(); + ruleDto = underTest.selectOrFailByKey(db.getSession(), organization, rule.getKey()); assertThat(ruleDto.getNoteData()).isEqualTo("My note"); assertThat(ruleDto.getNoteUserUuid()).isEqualTo("admin"); assertThat(ruleDto.getNoteCreatedAt()).isNotNull(); assertThat(ruleDto.getNoteUpdatedAt()).isNotNull(); assertThat(ruleDto.getRemediationFunction()).isEqualTo("LINEAR"); - assertThat(ruleDto.getDefRemediationFunction()).isNull(); assertThat(ruleDto.getRemediationGapMultiplier()).isEqualTo("1h"); - assertThat(ruleDto.getDefRemediationGapMultiplier()).isNull(); assertThat(ruleDto.getRemediationBaseEffort()).isEqualTo("5min"); - assertThat(ruleDto.getDefRemediationBaseEffort()).isNull(); - assertThat(ruleDto.getGapDescription()).isNull(); assertThat(ruleDto.getTags()).containsOnly("tag1", "tag2"); - assertThat(ruleDto.getSystemTags()).isEmpty(); + assertThat(ruleDto.getAdHocName()).isEqualTo("ad hoc name"); + assertThat(ruleDto.getAdHocDescription()).isEqualTo("ad hoc desc"); + assertThat(ruleDto.getAdHocSeverity()).isEqualTo(Severity.BLOCKER); + assertThat(ruleDto.getAdHocType()).isEqualTo(RuleType.CODE_SMELL.getDbConstant()); assertThat(ruleDto.getSecurityStandards()).isEmpty(); - assertThat(ruleDto.getType()).isEqualTo(0); assertThat(ruleDto.getCreatedAt()).isEqualTo(3_500_000_000_000L); assertThat(ruleDto.getUpdatedAt()).isEqualTo(7_000_000_000_000L); } @Test public void select_parameters_by_rule_key() { - db.prepareDbUnit(getClass(), "select_parameters_by_rule_key.xml"); - List ruleDtos = underTest.selectRuleParamsByRuleKey(db.getSession(), RuleKey.of("checkstyle", "AvoidNull")); + RuleDefinitionDto rule = db.rules().insert(); + RuleParamDto ruleParam = db.rules().insertRuleParam(rule); + + List ruleDtos = underTest.selectRuleParamsByRuleKey(db.getSession(), rule.getKey()); assertThat(ruleDtos.size()).isEqualTo(1); RuleParamDto ruleDto = ruleDtos.get(0); - assertThat(ruleDto.getId()).isEqualTo(1); - assertThat(ruleDto.getName()).isEqualTo("myParameter"); - assertThat(ruleDto.getDescription()).isEqualTo("My Parameter"); - assertThat(ruleDto.getType()).isEqualTo("plop"); - assertThat(ruleDto.getRuleId()).isEqualTo(1); + assertThat(ruleDto.getId()).isEqualTo(ruleParam.getId()); + assertThat(ruleDto.getName()).isEqualTo(ruleParam.getName()); + assertThat(ruleDto.getDescription()).isEqualTo(ruleParam.getDescription()); + assertThat(ruleDto.getType()).isEqualTo(ruleParam.getType()); + assertThat(ruleDto.getRuleId()).isEqualTo(rule.getId()); } @Test public void select_parameters_by_rule_keys() { - db.prepareDbUnit(getClass(), "select_parameters_by_rule_key.xml"); + RuleDefinitionDto rule1 = db.rules().insert(); + db.rules().insertRuleParam(rule1); + RuleDefinitionDto rule2 = db.rules().insert(); + db.rules().insertRuleParam(rule2); assertThat(underTest.selectRuleParamsByRuleKeys(db.getSession(), - Arrays.asList(RuleKey.of("checkstyle", "AvoidNull"), RuleKey.of("unused", "Unused")))).hasSize(2); + Arrays.asList(rule1.getKey(), rule2.getKey()))).hasSize(2); assertThat(underTest.selectRuleParamsByRuleKeys(db.getSession(), singletonList(RuleKey.of("unknown", "Unknown")))).isEmpty(); @@ -792,35 +769,36 @@ public class RuleDaoTest { @Test public void update_parameter() { - db.prepareDbUnit(getClass(), "update_parameter.xml"); - - RuleDefinitionDto rule1 = underTest.selectOrFailDefinitionByKey(db.getSession(), RuleKey.of("checkstyle", "AvoidNull")); + RuleDefinitionDto rule = db.rules().insert(); + RuleParamDto ruleParam = db.rules().insertRuleParam(rule); - List params = underTest.selectRuleParamsByRuleKey(db.getSession(), rule1.getKey()); + List params = underTest.selectRuleParamsByRuleKey(db.getSession(), rule.getKey()); assertThat(params).hasSize(1); - - RuleParamDto param = Iterables.getFirst(params, null); - param + RuleParamDto param = new RuleParamDto() + .setId(ruleParam.getId()) + .setRuleId(rule.getId()) + // Name will not be updated .setName("format") .setType("STRING") .setDefaultValue("^[a-z]+(\\.[a-z][a-z0-9]*)*$") .setDescription("Regular expression used to check the package names against."); - underTest.updateRuleParam(db.getSession(), rule1, param); - db.getSession().commit(); + underTest.updateRuleParam(db.getSession(), rule, param); - db.assertDbUnit(getClass(), "update_parameter-result.xml", "rules_parameters"); + assertThat(underTest.selectRuleParamsByRuleKey(db.getSession(), rule.getKey())) + .extracting(RuleParamDto::getName, RuleParamDto::getType, RuleParamDto::getDefaultValue, RuleParamDto::getDescription) + .containsExactlyInAnyOrder(tuple(ruleParam.getName(), "STRING", "^[a-z]+(\\.[a-z][a-z0-9]*)*$", "Regular expression used to check the package names against.")); } @Test public void delete_parameter() { - db.prepareDbUnit(getClass(), "select_parameters_by_rule_key.xml"); - assertThat(underTest.selectRuleParamsByRuleKey(db.getSession(), RuleKey.of("checkstyle", "AvoidNull"))).hasSize(1); + RuleDefinitionDto rule = db.rules().insert(); + RuleParamDto ruleParam = db.rules().insertRuleParam(rule); + assertThat(underTest.selectRuleParamsByRuleKey(db.getSession(), rule.getKey())).hasSize(1); - underTest.deleteRuleParam(db.getSession(), 1); - db.getSession().commit(); + underTest.deleteRuleParam(db.getSession(), ruleParam.getId()); - assertThat(underTest.selectRuleParamsByRuleKey(db.getSession(), RuleKey.of("checkstyle", "AvoidNull"))).isEmpty(); + assertThat(underTest.selectRuleParamsByRuleKey(db.getSession(), rule.getKey())).isEmpty(); } @Test @@ -867,7 +845,6 @@ public class RuleDaoTest { RuleForIndexingDto secondRule = it.next(); assertThat(secondRule.isExternal()).isTrue(); - } @Test diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleTesting.java b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleTesting.java index 2828c0e8ce2..6c725b66542 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleTesting.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleTesting.java @@ -78,6 +78,8 @@ public class RuleTesting { .setConfigKey("configKey_" + randomAlphanumeric(5)) .setSeverity(Severity.ALL.get(nextInt(Severity.ALL.size()))) .setIsTemplate(false) + .setIsExternal(false) + .setIsAdHoc(false) .setSystemTags(newHashSet("tag_" + randomAlphanumeric(5), "tag_" + randomAlphanumeric(5))) .setLanguage("lang_" + randomAlphanumeric(3)) .setGapDescription("gapDescription_" + randomAlphanumeric(5)) diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_parameter-result.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_parameter-result.xml deleted file mode 100644 index 36b0c887fcd..00000000000 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_parameter-result.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - 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 deleted file mode 100644 index 8c39a2d111c..00000000000 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_parameter.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - 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 deleted file mode 100644 index 593a6a4a042..00000000000 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectEnabled.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - 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 deleted file mode 100644 index faebb444a42..00000000000 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectNonManual.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - 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 deleted file mode 100644 index 49b9773832a..00000000000 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_parameters_by_rule_key.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/shared.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/shared.xml deleted file mode 100644 index 5014ce59d64..00000000000 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/shared.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - 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 deleted file mode 100644 index b0050d14b7f..00000000000 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - 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 deleted file mode 100644 index bb3801df484..00000000000 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter-result.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 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 deleted file mode 100644 index 484f86c62c5..00000000000 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java index 0e4b55a68e0..f5ffda01c3d 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java @@ -37,6 +37,7 @@ import org.sonar.server.platform.db.migration.version.v70.DbVersion70; import org.sonar.server.platform.db.migration.version.v71.DbVersion71; import org.sonar.server.platform.db.migration.version.v72.DbVersion72; import org.sonar.server.platform.db.migration.version.v73.DbVersion73; +import org.sonar.server.platform.db.migration.version.v74.DbVersion74; public class MigrationConfigurationModule extends Module { @Override @@ -57,6 +58,7 @@ public class MigrationConfigurationModule extends Module { DbVersion71.class, DbVersion72.class, DbVersion73.class, + DbVersion74.class, // migration steps MigrationStepRegistryImpl.class, diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddIsAdHocToRules.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddIsAdHocToRules.java new file mode 100644 index 00000000000..ff1e16d387b --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/AddIsAdHocToRules.java @@ -0,0 +1,47 @@ +/* + * 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.v74; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.SupportsBlueGreen; +import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder; +import org.sonar.server.platform.db.migration.step.DdlChange; + +import static org.sonar.server.platform.db.migration.def.BooleanColumnDef.newBooleanColumnDefBuilder; + +@SupportsBlueGreen +public class AddIsAdHocToRules extends DdlChange { + + public AddIsAdHocToRules(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + context.execute(new AddColumnsBuilder(getDialect(), "rules") + .addColumn(newBooleanColumnDefBuilder() + .setColumnName("is_ad_hoc") + .setIsNullable(true) + .build()) + .build()); + } + +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74.java new file mode 100644 index 00000000000..569a5ac2e7c --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74.java @@ -0,0 +1,36 @@ +/* + * 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.v74; + +import org.sonar.server.platform.db.migration.step.MigrationStepRegistry; +import org.sonar.server.platform.db.migration.version.DbVersion; + +public class DbVersion74 implements DbVersion { + + @Override + public void addSteps(MigrationStepRegistry registry) { + registry + .add(2300, "Populate null values of IS_EXTERNAL in RULES", PopulateNullValuesOfIsExternalOnRules.class) + .add(2301, "Add IS_ADHOC column to RULES table", AddIsAdHocToRules.class) + .add(2302, "Populate IS_AD_HOC in RULES", PopulateIsAdHocOnRules.class) + .add(2303, "Set IS_EXTERNAL and IS_AD_HOC not nullable in RULES", SetIsExternalAndIsAdHocNotNullableInRules.class) + ; + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateIsAdHocOnRules.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateIsAdHocOnRules.java new file mode 100644 index 00000000000..716b5977b71 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateIsAdHocOnRules.java @@ -0,0 +1,54 @@ +/* + * 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.v74; + +import java.sql.SQLException; +import org.sonar.api.utils.System2; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.SupportsBlueGreen; +import org.sonar.server.platform.db.migration.step.DataChange; +import org.sonar.server.platform.db.migration.step.MassUpdate; + +@SupportsBlueGreen +public class PopulateIsAdHocOnRules extends DataChange { + + private final System2 system2; + + public PopulateIsAdHocOnRules(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().rowPluralName("rules"); + massUpdate.select("SELECT r.id, r.is_external FROM rules r WHERE r.is_ad_hoc IS NULL"); + massUpdate.update("UPDATE rules SET is_ad_hoc=?, updated_at=? WHERE id=?"); + massUpdate.execute((row, update) -> { + int id = row.getInt(1); + update.setBoolean(1, row.getBoolean(2)); + update.setLong(2, now); + update.setInt(3, id); + return true; + }); + } + +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateNullValuesOfIsExternalOnRules.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateNullValuesOfIsExternalOnRules.java new file mode 100644 index 00000000000..120a7c08c70 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/PopulateNullValuesOfIsExternalOnRules.java @@ -0,0 +1,54 @@ +/* + * 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.v74; + +import java.sql.SQLException; +import org.sonar.api.utils.System2; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.SupportsBlueGreen; +import org.sonar.server.platform.db.migration.step.DataChange; +import org.sonar.server.platform.db.migration.step.MassUpdate; + +@SupportsBlueGreen +public class PopulateNullValuesOfIsExternalOnRules extends DataChange { + + private final System2 system2; + + public PopulateNullValuesOfIsExternalOnRules(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().rowPluralName("rules"); + massUpdate.select("SELECT r.id FROM rules r WHERE r.is_external IS NULL"); + massUpdate.update("UPDATE rules SET is_external=?, updated_at=? WHERE id=?"); + massUpdate.execute((row, update) -> { + int id = row.getInt(1); + update.setBoolean(1, false); + update.setLong(2, now); + update.setInt(3, id); + return true; + }); + } + +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/SetIsExternalAndIsAdHocNotNullableInRules.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/SetIsExternalAndIsAdHocNotNullableInRules.java new file mode 100644 index 00000000000..2c728520e78 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/SetIsExternalAndIsAdHocNotNullableInRules.java @@ -0,0 +1,50 @@ +/* + * 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.v74; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.SupportsBlueGreen; +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.BooleanColumnDef.newBooleanColumnDefBuilder; + +@SupportsBlueGreen +public class SetIsExternalAndIsAdHocNotNullableInRules extends DdlChange { + + public SetIsExternalAndIsAdHocNotNullableInRules(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + context.execute(new AlterColumnsBuilder(getDialect(), "rules") + .updateColumn(newBooleanColumnDefBuilder() + .setColumnName("is_external") + .setIsNullable(false) + .build()) + .updateColumn(newBooleanColumnDefBuilder() + .setColumnName("is_ad_hoc") + .setIsNullable(false) + .build()) + .build()); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/package-info.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/package-info.java new file mode 100644 index 00000000000..d57baa7fee0 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/package-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.platform.db.migration.version.v74; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationConfigurationModuleTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationConfigurationModuleTest.java index 5ff4a49cd98..f0d5c74a350 100644 --- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationConfigurationModuleTest.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/MigrationConfigurationModuleTest.java @@ -37,7 +37,7 @@ public class MigrationConfigurationModuleTest { assertThat(container.getPicoContainer().getComponentAdapters()) .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER // DbVersion classes - + 14 + + 15 // Others + 3); } diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/AddIsAdHocToRulesTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/AddIsAdHocToRulesTest.java new file mode 100644 index 00000000000..2b30280d769 --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/AddIsAdHocToRulesTest.java @@ -0,0 +1,55 @@ +/* + * 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.v74; + +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.BOOLEAN; + +public class AddIsAdHocToRulesTest { + @Rule + public final CoreDbTester db = CoreDbTester.createForSchema(AddIsAdHocToRulesTest.class, "rules.sql"); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private AddIsAdHocToRules underTest = new AddIsAdHocToRules(db.database()); + + @Test + public void column_is_added_to_table() throws SQLException { + underTest.execute(); + + db.assertColumnDefinition("rules", "is_ad_hoc", BOOLEAN, 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/v74/DbVersion74Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74Test.java new file mode 100644 index 00000000000..28062983699 --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74Test.java @@ -0,0 +1,40 @@ +/* + * 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.v74; + +import org.junit.Test; + +import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationCount; +import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMinimumMigrationNumber; + +public class DbVersion74Test { + + private DbVersion74 underTest = new DbVersion74(); + + @Test + public void migrationNumber_starts_at_2300() { + verifyMinimumMigrationNumber(underTest, 2300); + } + + @Test + public void verify_migration_count() { + verifyMigrationCount(underTest, 4); + } +} diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/PopulateIsAdHocOnRulesTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/PopulateIsAdHocOnRulesTest.java new file mode 100644 index 00000000000..f8616e3451e --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/PopulateIsAdHocOnRulesTest.java @@ -0,0 +1,120 @@ +/* + * 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.v74; + +import java.sql.SQLException; +import java.util.stream.Collectors; +import javax.annotation.Nullable; +import org.assertj.core.groups.Tuple; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.utils.System2; +import org.sonar.api.utils.internal.TestSystem2; +import org.sonar.db.CoreDbTester; + +import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; + +public class PopulateIsAdHocOnRulesTest { + + private final static long PAST = 10_000_000_000L; + private final static long NOW = 50_000_000_000L; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + @Rule + public CoreDbTester db = CoreDbTester.createForSchema(PopulateIsAdHocOnRulesTest.class, "rules.sql"); + + private System2 system2 = new TestSystem2().setNow(NOW); + + private PopulateIsAdHocOnRules underTest = new PopulateIsAdHocOnRules(db.database(), system2); + + @Test + public void set_is_ad_hoc_to_true_on_external_rules() throws SQLException { + insertRule(1, true, null); + insertRule(2, true, null); + + underTest.execute(); + + assertRules( + tuple(1L, true, true, NOW), + tuple(2L, true, true, NOW)); + } + + @Test + public void set_is_ad_hoc_to_false_on_none_external_rules() throws SQLException { + insertRule(1, false, null); + insertRule(2, false, null); + + underTest.execute(); + + assertRules( + tuple(1L, false, false, NOW), + tuple(2L, false, false, NOW)); + } + + @Test + public void does_nothing_when_is_ad_hoc_is_already_set() throws SQLException { + insertRule(1, true, true); + insertRule(2, false, false); + + underTest.execute(); + + assertRules( + tuple(1L, true, true, PAST), + tuple(2L, false, false, PAST)); + } + + @Test + public void migration_is_re_entrant() throws SQLException { + insertRule(1, true, null); + insertRule(2, false, null); + + underTest.execute(); + underTest.execute(); + + assertRules( + tuple(1L, true, true, NOW), + tuple(2L, false, false, NOW)); + } + + private void assertRules(Tuple... expectedTuples) { + assertThat(db.select("SELECT ID, IS_EXTERNAL, IS_AD_HOC, UPDATED_AT FROM RULES") + .stream() + .map(row -> new Tuple(row.get("ID"), row.get("IS_EXTERNAL"), row.get("IS_AD_HOC"), row.get("UPDATED_AT"))) + .collect(Collectors.toList())) + .containsExactlyInAnyOrder(expectedTuples); + } + + private void insertRule(int id, boolean isEternal, @Nullable Boolean isAdHoc) { + db.executeInsert("RULES", + "ID", id, + "IS_EXTERNAL", isEternal, + "IS_AD_HOC", isAdHoc, + "PLUGIN_RULE_KEY", randomAlphanumeric(3), + "PLUGIN_NAME", randomAlphanumeric(3), + "SCOPE", "MAIN", + "CREATED_AT", PAST, + "UPDATED_AT", PAST); + } + +} diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/PopulateNullValuesOfIsExternalOnRulesTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/PopulateNullValuesOfIsExternalOnRulesTest.java new file mode 100644 index 00000000000..963f74af111 --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/PopulateNullValuesOfIsExternalOnRulesTest.java @@ -0,0 +1,105 @@ +/* + * 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.v74; + +import java.sql.SQLException; +import java.util.stream.Collectors; +import javax.annotation.Nullable; +import org.assertj.core.groups.Tuple; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.utils.System2; +import org.sonar.api.utils.internal.TestSystem2; +import org.sonar.db.CoreDbTester; + +import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; + +public class PopulateNullValuesOfIsExternalOnRulesTest { + + private final static long PAST = 10_000_000_000L; + private final static long NOW = 50_000_000_000L; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + @Rule + public CoreDbTester db = CoreDbTester.createForSchema(PopulateNullValuesOfIsExternalOnRulesTest.class, "rules.sql"); + + private System2 system2 = new TestSystem2().setNow(NOW); + + private PopulateNullValuesOfIsExternalOnRules underTest = new PopulateNullValuesOfIsExternalOnRules(db.database(), system2); + + @Test + public void set_is_external_to_false() throws SQLException { + insertRule(1, null); + insertRule(2, null); + + underTest.execute(); + + assertRules( + tuple(1L, false, NOW), + tuple(2L, false, NOW)); + } + + @Test + public void does_nothing_when_is_external_is_already_set() throws SQLException { + insertRule(1, true); + insertRule(2, false); + + underTest.execute(); + + assertRules( + tuple(1L, true, PAST), + tuple(2L, false, PAST)); + } + + @Test + public void migration_is_re_entrant() throws SQLException { + insertRule(1, null); + + underTest.execute(); + underTest.execute(); + + assertRules( + tuple(1L, false, NOW)); + } + + private void assertRules(Tuple... expectedTuples) { + assertThat(db.select("SELECT ID, IS_EXTERNAL, UPDATED_AT FROM RULES") + .stream() + .map(row -> new Tuple(row.get("ID"), row.get("IS_EXTERNAL"), row.get("UPDATED_AT"))) + .collect(Collectors.toList())) + .containsExactlyInAnyOrder(expectedTuples); + } + + private void insertRule(int id, @Nullable Boolean isEternal) { + db.executeInsert("RULES", + "ID", id, + "IS_EXTERNAL", isEternal, + "PLUGIN_RULE_KEY", randomAlphanumeric(3), + "PLUGIN_NAME", randomAlphanumeric(3), + "SCOPE", "MAIN", + "CREATED_AT", PAST, + "UPDATED_AT", PAST); + } + +} diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/SetIsExternalAndIsAdHocNotNullableInRulesTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/SetIsExternalAndIsAdHocNotNullableInRulesTest.java new file mode 100644 index 00000000000..62b6183e645 --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/SetIsExternalAndIsAdHocNotNullableInRulesTest.java @@ -0,0 +1,54 @@ +/* + * 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.v74; + +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.BOOLEAN; + +public class SetIsExternalAndIsAdHocNotNullableInRulesTest { + @Rule + public final CoreDbTester db = CoreDbTester.createForSchema(SetIsExternalAndIsAdHocNotNullableInRulesTest.class, "rules.sql"); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private SetIsExternalAndIsAdHocNotNullableInRules underTest = new SetIsExternalAndIsAdHocNotNullableInRules(db.database()); + + @Test + public void columns_are_updated() throws SQLException { + underTest.execute(); + + db.assertColumnDefinition("rules", "is_external", BOOLEAN, null, false); + db.assertColumnDefinition("rules", "is_ad_hoc", BOOLEAN, null, false); + } + + @Test + public void migration_is_reentrant() throws SQLException { + underTest.execute(); + + underTest.execute(); + } + +} diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/AddIsAdHocToRulesTest/rules.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/AddIsAdHocToRulesTest/rules.sql new file mode 100644 index 00000000000..19fd9844826 --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/AddIsAdHocToRulesTest/rules.sql @@ -0,0 +1,27 @@ +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, + "IS_EXTERNAL" BOOLEAN, + "TEMPLATE_ID" INTEGER, + "PLUGIN_CONFIG_KEY" VARCHAR(200), + "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), + "GAP_DESCRIPTION" VARCHAR(4000), + "SYSTEM_TAGS" VARCHAR(4000), + "SECURITY_STANDARDS" VARCHAR(4000), + "RULE_TYPE" TINYINT, + "CREATED_AT" BIGINT, + "UPDATED_AT" BIGINT +); +CREATE UNIQUE INDEX "RULES_REPO_KEY" ON "RULES" ("PLUGIN_NAME", "PLUGIN_RULE_KEY"); \ No newline at end of file diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/PopulateIsAdHocOnRulesTest/rules.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/PopulateIsAdHocOnRulesTest/rules.sql new file mode 100644 index 00000000000..2179b79d9ad --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/PopulateIsAdHocOnRulesTest/rules.sql @@ -0,0 +1,28 @@ +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, + "IS_EXTERNAL" BOOLEAN, + "IS_AD_HOC" BOOLEAN, + "TEMPLATE_ID" INTEGER, + "PLUGIN_CONFIG_KEY" VARCHAR(200), + "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), + "GAP_DESCRIPTION" VARCHAR(4000), + "SYSTEM_TAGS" VARCHAR(4000), + "SECURITY_STANDARDS" VARCHAR(4000), + "RULE_TYPE" TINYINT, + "CREATED_AT" BIGINT, + "UPDATED_AT" BIGINT +); +CREATE UNIQUE INDEX "RULES_REPO_KEY" ON "RULES" ("PLUGIN_NAME", "PLUGIN_RULE_KEY"); \ No newline at end of file diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/PopulateNullValuesOfIsExternalOnRulesTest/rules.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/PopulateNullValuesOfIsExternalOnRulesTest/rules.sql new file mode 100644 index 00000000000..19fd9844826 --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/PopulateNullValuesOfIsExternalOnRulesTest/rules.sql @@ -0,0 +1,27 @@ +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, + "IS_EXTERNAL" BOOLEAN, + "TEMPLATE_ID" INTEGER, + "PLUGIN_CONFIG_KEY" VARCHAR(200), + "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), + "GAP_DESCRIPTION" VARCHAR(4000), + "SYSTEM_TAGS" VARCHAR(4000), + "SECURITY_STANDARDS" VARCHAR(4000), + "RULE_TYPE" TINYINT, + "CREATED_AT" BIGINT, + "UPDATED_AT" BIGINT +); +CREATE UNIQUE INDEX "RULES_REPO_KEY" ON "RULES" ("PLUGIN_NAME", "PLUGIN_RULE_KEY"); \ No newline at end of file diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/SetIsExternalAndIsAdHocNotNullableInRulesTest/rules.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/SetIsExternalAndIsAdHocNotNullableInRulesTest/rules.sql new file mode 100644 index 00000000000..2179b79d9ad --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/SetIsExternalAndIsAdHocNotNullableInRulesTest/rules.sql @@ -0,0 +1,28 @@ +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, + "IS_EXTERNAL" BOOLEAN, + "IS_AD_HOC" BOOLEAN, + "TEMPLATE_ID" INTEGER, + "PLUGIN_CONFIG_KEY" VARCHAR(200), + "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), + "GAP_DESCRIPTION" VARCHAR(4000), + "SYSTEM_TAGS" VARCHAR(4000), + "SECURITY_STANDARDS" VARCHAR(4000), + "RULE_TYPE" TINYINT, + "CREATED_AT" BIGINT, + "UPDATED_AT" BIGINT +); +CREATE UNIQUE INDEX "RULES_REPO_KEY" ON "RULES" ("PLUGIN_NAME", "PLUGIN_RULE_KEY"); \ No newline at end of file diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/rule/ExternalRuleCreatorTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/rule/ExternalRuleCreatorTest.java index 32b9d329e79..59d4d28fcfe 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/rule/ExternalRuleCreatorTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/rule/ExternalRuleCreatorTest.java @@ -54,6 +54,7 @@ public class ExternalRuleCreatorTest { assertThat(rule1).isNotNull(); assertThat(rule1.isExternal()).isTrue(); + assertThat(rule1.isAdHoc()).isTrue(); assertThat(rule1.getId()).isGreaterThan(0); assertThat(rule1.getKey()).isEqualTo(ruleKey); assertThat(rule1.getPluginKey()).isEqualTo("eslint"); diff --git a/server/sonar-server-common/src/test/resources/org/sonar/server/issue/index/IssueIteratorFactoryTest/extract_directory_path.xml b/server/sonar-server-common/src/test/resources/org/sonar/server/issue/index/IssueIteratorFactoryTest/extract_directory_path.xml index 5af7683e247..d257bf0cd05 100644 --- a/server/sonar-server-common/src/test/resources/org/sonar/server/issue/index/IssueIteratorFactoryTest/extract_directory_path.xml +++ b/server/sonar-server-common/src/test/resources/org/sonar/server/issue/index/IssueIteratorFactoryTest/extract_directory_path.xml @@ -5,7 +5,10 @@ plugin_rule_key="AvoidCycles" plugin_config_key="[null]" plugin_name="squid" - scope="MAIN"/> + scope="MAIN" + is_external="[false]" + is_ad_hoc="[false]" + /> + scope="MAIN" + is_external="[false]" + is_ad_hoc="[false]" + /> + scope="MAIN" + is_external="[false]" + is_ad_hoc="[false]" + /> + scope="MAIN" + is_external="[false]" + is_ad_hoc="[false]" + /> + scope="MAIN" + is_external="[false]" + is_ad_hoc="[false]" + /> { if (rule.isCustomRule()) { customRules.add(rule); - } else if (!rule.isExternal() && rule.getStatus() != RuleStatus.REMOVED) { + } else if (!rule.isAdHoc() && rule.getStatus() != RuleStatus.REMOVED) { removeRule(dbSession, recorder, rule); } }); diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java index 78b157c4eb0..d5c423a5072 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java @@ -171,6 +171,8 @@ public class RuleCreator { .setScope(templateRuleDto.getScope()) .setSystemTags(templateRuleDto.getSystemTags()) .setSecurityStandards(templateRuleDto.getSecurityStandards()) + .setIsExternal(false) + .setIsAdHoc(false) .setCreatedAt(system2.now()) .setUpdatedAt(system2.now()); dbClient.ruleDao().insert(dbSession, ruleDefinition); diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/IssuesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/IssuesActionTest.java index 35961c13d98..c64953012ee 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/batch/IssuesActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/batch/IssuesActionTest.java @@ -182,7 +182,7 @@ public class IssuesActionTest { IssueDto issueFromExteralruleOnFile = db.issues().insert(external, project, file, i -> i.setKee("ON_FILE_FROM_EXTERNAL").setType(randomRuleTypeExceptHotspot())); RuleDefinitionDto migrated = db.rules().insert(); - db.executeUpdateSql("update rules set is_external = NULL where rules.id = ?", migrated.getId()); + db.executeUpdateSql("update rules set is_external=? where rules.id = ?", false, migrated.getId()); IssueDto issueFromMigratedRule = db.issues().insert(migrated, project, file, i -> i.setKee("MIGRATED").setType(randomRuleTypeExceptHotspot())); addPermissionTo(project); 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 270d5d4e3ae..c80a87ce15b 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 @@ -79,6 +79,8 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.sonar.api.rule.RuleStatus.READY; +import static org.sonar.api.rule.RuleStatus.REMOVED; import static org.sonar.api.rule.Severity.BLOCKER; import static org.sonar.api.rule.Severity.INFO; import static org.sonar.api.server.rule.RulesDefinition.NewRepository; @@ -105,7 +107,7 @@ public class RegisterRulesTest { @org.junit.Rule public ExpectedException expectedException = ExpectedException.none(); @org.junit.Rule - public DbTester dbTester = DbTester.create(system); + public DbTester db = DbTester.create(system); @org.junit.Rule public EsTester es = EsTester.create(); @org.junit.Rule @@ -113,7 +115,7 @@ public class RegisterRulesTest { private QProfileRules qProfileRules = mock(QProfileRules.class); private WebServerRuleFinder webServerRuleFinder = mock(WebServerRuleFinder.class); - private DbClient dbClient = dbTester.getDbClient(); + private DbClient dbClient = db.getDbClient(); private RuleIndexer ruleIndexer; private ActiveRuleIndexer activeRuleIndexer; private RuleIndex ruleIndex; @@ -127,7 +129,7 @@ public class RegisterRulesTest { ruleIndexer = new RuleIndexer(es.client(), dbClient); ruleIndex = new RuleIndex(es.client(), system); activeRuleIndexer = new ActiveRuleIndexer(dbClient, es.client()); - defaultOrganization = dbTester.getDefaultOrganization(); + defaultOrganization = db.getDefaultOrganization(); } @Test @@ -135,8 +137,8 @@ public class RegisterRulesTest { execute(new FakeRepositoryV1()); // verify db - assertThat(dbClient.ruleDao().selectAllDefinitions(dbTester.getSession())).hasSize(3); - RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), dbTester.getDefaultOrganization(), RULE_KEY1); + assertThat(dbClient.ruleDao().selectAllDefinitions(db.getSession())).hasSize(3); + RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), db.getDefaultOrganization(), RULE_KEY1); assertThat(rule1.getName()).isEqualTo("One"); assertThat(rule1.getDescription()).isEqualTo("Description of One"); assertThat(rule1.getSeverityString()).isEqualTo(BLOCKER); @@ -153,8 +155,9 @@ public class RegisterRulesTest { assertThat(rule1.getType()).isEqualTo(RuleType.CODE_SMELL.getDbConstant()); assertThat(rule1.getPluginKey()).isEqualTo(FAKE_PLUGIN_KEY); assertThat(rule1.isExternal()).isFalse(); + assertThat(rule1.isAdHoc()).isFalse(); - RuleDto hotspotRule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), dbTester.getDefaultOrganization(), HOTSPOT_RULE_KEY); + RuleDto hotspotRule = dbClient.ruleDao().selectOrFailByKey(db.getSession(), db.getDefaultOrganization(), HOTSPOT_RULE_KEY); assertThat(hotspotRule.getName()).isEqualTo("Hotspot"); assertThat(hotspotRule.getDescription()).isEqualTo("Minimal hotspot"); assertThat(hotspotRule.getCreatedAt()).isEqualTo(DATE1.getTime()); @@ -162,18 +165,18 @@ public class RegisterRulesTest { assertThat(hotspotRule.getType()).isEqualTo(RuleType.SECURITY_HOTSPOT.getDbConstant()); assertThat(hotspotRule.getSecurityStandards()).containsExactly("cwe:1", "cwe:123", "cwe:863", "owaspTop10:a1", "owaspTop10:a3"); - List params = dbClient.ruleDao().selectRuleParamsByRuleKey(dbTester.getSession(), RULE_KEY1); + List params = dbClient.ruleDao().selectRuleParamsByRuleKey(db.getSession(), RULE_KEY1); assertThat(params).hasSize(2); RuleParamDto param = getParam(params, "param1"); assertThat(param.getDescription()).isEqualTo("parameter one"); assertThat(param.getDefaultValue()).isEqualTo("default1"); // verify index - RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), dbTester.getDefaultOrganization(), RULE_KEY2); + RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), db.getDefaultOrganization(), RULE_KEY2); assertThat(ruleIndex.search(new RuleQuery(), new SearchOptions()).getIds()).containsOnly(rule1.getId(), rule2.getId(), hotspotRule.getId()); // verify repositories - assertThat(dbClient.ruleRepositoryDao().selectAll(dbTester.getSession())).extracting(RuleRepositoryDto::getKey).containsOnly("fake"); + assertThat(dbClient.ruleRepositoryDao().selectAll(db.getSession())).extracting(RuleRepositoryDto::getKey).containsOnly("fake"); } @Test @@ -181,8 +184,8 @@ public class RegisterRulesTest { execute(new ExternalRuleRepository()); // verify db - assertThat(dbClient.ruleDao().selectAllDefinitions(dbTester.getSession())).hasSize(2); - RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), dbTester.getDefaultOrganization(), EXTERNAL_RULE_KEY1); + assertThat(dbClient.ruleDao().selectAllDefinitions(db.getSession())).hasSize(2); + RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), db.getDefaultOrganization(), EXTERNAL_RULE_KEY1); assertThat(rule1.getName()).isEqualTo("One"); assertThat(rule1.getDescription()).isEqualTo("Description of One"); assertThat(rule1.getSeverityString()).isEqualTo(BLOCKER); @@ -199,8 +202,9 @@ public class RegisterRulesTest { assertThat(rule1.getType()).isEqualTo(RuleType.CODE_SMELL.getDbConstant()); assertThat(rule1.getPluginKey()).isEqualTo(FAKE_PLUGIN_KEY); assertThat(rule1.isExternal()).isTrue(); + assertThat(rule1.isAdHoc()).isFalse(); - RuleDto hotspotRule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), dbTester.getDefaultOrganization(), EXTERNAL_HOTSPOT_RULE_KEY); + RuleDto hotspotRule = dbClient.ruleDao().selectOrFailByKey(db.getSession(), db.getDefaultOrganization(), EXTERNAL_HOTSPOT_RULE_KEY); assertThat(hotspotRule.getName()).isEqualTo("Hotspot"); assertThat(hotspotRule.getDescription()).isEqualTo("Minimal hotspot"); assertThat(hotspotRule.getCreatedAt()).isEqualTo(DATE1.getTime()); @@ -223,7 +227,7 @@ public class RegisterRulesTest { }); // verify db - List rules = dbClient.ruleDao().selectAllDefinitions(dbTester.getSession()); + List rules = dbClient.ruleDao().selectAllDefinitions(db.getSession()); assertThat(rules) .extracting(RuleDefinitionDto::getKey) .extracting(RuleKey::rule) @@ -238,13 +242,13 @@ public class RegisterRulesTest { execute(context -> context.createRepository("fake", "java").done()); // verify db - assertThat(dbClient.ruleDao().selectAllDefinitions(dbTester.getSession())) + assertThat(dbClient.ruleDao().selectAllDefinitions(db.getSession())) .extracting(RuleDefinitionDto::getKey) .extracting(RuleKey::rule) .containsExactly(ruleKey); - assertThat(dbClient.ruleDao().selectAllDefinitions(dbTester.getSession())) + assertThat(dbClient.ruleDao().selectAllDefinitions(db.getSession())) .extracting(RuleDefinitionDto::getStatus) - .containsExactly(RuleStatus.REMOVED); + .containsExactly(REMOVED); // verify index assertThat(ruleIndex.search(new RuleQuery(), new SearchOptions()).getIds()) @@ -267,10 +271,10 @@ public class RegisterRulesTest { }); // verify db - assertThat(dbClient.ruleDao().selectAllDefinitions(dbTester.getSession())) + assertThat(dbClient.ruleDao().selectAllDefinitions(db.getSession())) .hasSize(numberOfRules) .extracting(RuleDefinitionDto::getStatus) - .containsOnly(RuleStatus.READY); + .containsOnly(READY); // verify index assertThat(es.countDocuments(RuleIndexDefinition.INDEX_TYPE_RULE)).isEqualTo(numberOfRules); @@ -281,10 +285,10 @@ public class RegisterRulesTest { execute(context -> context.createRepository("fake", "java").done()); // verify db - assertThat(dbClient.ruleDao().selectAllDefinitions(dbTester.getSession())) + assertThat(dbClient.ruleDao().selectAllDefinitions(db.getSession())) .hasSize(numberOfRules) .extracting(RuleDefinitionDto::getStatus) - .containsOnly(RuleStatus.REMOVED); + .containsOnly(REMOVED); // verify index (documents are still in the index, but all are removed) assertThat(es.countDocuments(RuleIndexDefinition.INDEX_TYPE_RULE)).isEqualTo(numberOfRules); @@ -295,36 +299,36 @@ public class RegisterRulesTest { @Test public void delete_repositories_that_have_been_uninstalled() { RuleRepositoryDto repository = new RuleRepositoryDto("findbugs", "java", "Findbugs"); - DbSession dbSession = dbTester.getSession(); - dbTester.getDbClient().ruleRepositoryDao().insertOrUpdate(dbSession, singletonList(repository)); + DbSession dbSession = db.getSession(); + db.getDbClient().ruleRepositoryDao().insertOrUpdate(dbSession, singletonList(repository)); dbSession.commit(); execute(new FakeRepositoryV1()); - assertThat(dbTester.getDbClient().ruleRepositoryDao().selectAll(dbSession)).extracting(RuleRepositoryDto::getKey).containsOnly("fake"); + assertThat(db.getDbClient().ruleRepositoryDao().selectAll(dbSession)).extracting(RuleRepositoryDto::getKey).containsOnly("fake"); } @Test public void update_and_remove_rules_on_changes() { execute(new FakeRepositoryV1()); - assertThat(dbClient.ruleDao().selectAllDefinitions(dbTester.getSession())).hasSize(3); - RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1); - RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY2); - RuleDto hotspotRule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, HOTSPOT_RULE_KEY); + assertThat(dbClient.ruleDao().selectAllDefinitions(db.getSession())).hasSize(3); + RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY1); + RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY2); + RuleDto hotspotRule = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, HOTSPOT_RULE_KEY); assertThat(es.getIds(RuleIndexDefinition.INDEX_TYPE_RULE)).containsOnly(valueOf(rule1.getId()), valueOf(rule2.getId()), valueOf(hotspotRule.getId())); // user adds tags and sets markdown note rule1.setTags(newHashSet("usertag1", "usertag2")); rule1.setNoteData("user *note*"); rule1.setNoteUserUuid("marius"); - dbClient.ruleDao().insertOrUpdate(dbTester.getSession(), rule1.getMetadata()); - dbTester.getSession().commit(); + dbClient.ruleDao().insertOrUpdate(db.getSession(), rule1.getMetadata()); + db.getSession().commit(); when(system.now()).thenReturn(DATE2.getTime()); execute(new FakeRepositoryV2()); // rule1 has been updated - rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1); + rule1 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY1); assertThat(rule1.getName()).isEqualTo("One v2"); assertThat(rule1.getDescription()).isEqualTo("Description of One v2"); assertThat(rule1.getSeverityString()).isEqualTo(INFO); @@ -333,33 +337,33 @@ public class RegisterRulesTest { assertThat(rule1.getConfigKey()).isEqualTo("config1 v2"); assertThat(rule1.getNoteData()).isEqualTo("user *note*"); assertThat(rule1.getNoteUserUuid()).isEqualTo("marius"); - assertThat(rule1.getStatus()).isEqualTo(RuleStatus.READY); + assertThat(rule1.getStatus()).isEqualTo(READY); assertThat(rule1.getType()).isEqualTo(RuleType.BUG.getDbConstant()); assertThat(rule1.getCreatedAt()).isEqualTo(DATE1.getTime()); assertThat(rule1.getUpdatedAt()).isEqualTo(DATE2.getTime()); // TODO check remediation function - List params = dbClient.ruleDao().selectRuleParamsByRuleKey(dbTester.getSession(), RULE_KEY1); + List params = dbClient.ruleDao().selectRuleParamsByRuleKey(db.getSession(), RULE_KEY1); assertThat(params).hasSize(2); RuleParamDto param = getParam(params, "param1"); assertThat(param.getDescription()).isEqualTo("parameter one v2"); assertThat(param.getDefaultValue()).isEqualTo("default1 v2"); // rule2 has been removed -> status set to REMOVED but db row is not deleted - rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY2); - assertThat(rule2.getStatus()).isEqualTo(RuleStatus.REMOVED); + rule2 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY2); + assertThat(rule2.getStatus()).isEqualTo(REMOVED); assertThat(rule2.getUpdatedAt()).isEqualTo(DATE2.getTime()); // rule3 has been created - RuleDto rule3 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY3); + RuleDto rule3 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY3); assertThat(rule3).isNotNull(); - assertThat(rule3.getStatus()).isEqualTo(RuleStatus.READY); + assertThat(rule3.getStatus()).isEqualTo(READY); // verify index assertThat(ruleIndex.search(new RuleQuery(), new SearchOptions()).getIds()).containsOnly(rule1.getId(), rule3.getId()); // verify repositories - assertThat(dbClient.ruleRepositoryDao().selectAll(dbTester.getSession())).extracting(RuleRepositoryDto::getKey).containsOnly("fake"); + assertThat(dbClient.ruleRepositoryDao().selectAll(db.getSession())).extracting(RuleRepositoryDto::getKey).containsOnly("fake"); } @Test @@ -373,8 +377,8 @@ public class RegisterRulesTest { repo.done(); }); - OrganizationDto defaultOrganization = dbTester.getDefaultOrganization(); - RuleDto rule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1); + OrganizationDto defaultOrganization = db.getDefaultOrganization(); + RuleDto rule = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY1); assertThat(rule.getSystemTags()).containsOnly("tag1"); execute((RulesDefinition) context -> { @@ -386,7 +390,7 @@ public class RegisterRulesTest { repo.done(); }); - rule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1); + rule = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY1); assertThat(rule.getSystemTags()).containsOnly("tag1", "tag2"); } @@ -402,8 +406,8 @@ public class RegisterRulesTest { repo.done(); }); - OrganizationDto defaultOrganization = dbTester.getDefaultOrganization(); - RuleDto rule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1); + OrganizationDto defaultOrganization = db.getDefaultOrganization(); + RuleDto rule = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY1); assertThat(rule.getSecurityStandards()).containsOnly("cwe:123", "owaspTop10:a1"); execute((RulesDefinition) context -> { @@ -416,7 +420,7 @@ public class RegisterRulesTest { repo.done(); }); - rule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1); + rule = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY1); assertThat(rule.getSecurityStandards()).containsOnly("cwe:1", "cwe:123", "cwe:863", "owaspTop10:a1", "owaspTop10:a3"); } @@ -441,7 +445,7 @@ public class RegisterRulesTest { }); // rule1 has been updated - RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RuleKey.of("fake", "rule")); + RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RuleKey.of("fake", "rule")); assertThat(rule1.getName()).isEqualTo("Name2"); assertThat(rule1.getDescription()).isEqualTo("Description"); @@ -464,7 +468,7 @@ public class RegisterRulesTest { repo.done(); }); - RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RuleKey.of(repository, ruleKey1)); + RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RuleKey.of(repository, ruleKey1)); SearchIdResult searchRule1 = ruleIndex.search(new RuleQuery().setQueryText("Name1"), new SearchOptions()); assertThat(searchRule1.getIds()).containsOnly(rule1.getId()); assertThat(searchRule1.getTotal()).isEqualTo(1); @@ -480,7 +484,7 @@ public class RegisterRulesTest { }); // rule2 is actually rule1 - RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RuleKey.of(repository, ruleKey2)); + RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RuleKey.of(repository, ruleKey2)); assertThat(rule2.getId()).isEqualTo(rule1.getId()); assertThat(rule2.getName()).isEqualTo("Name2"); assertThat(rule2.getDescription()).isEqualTo(rule1.getDescription()); @@ -506,7 +510,7 @@ public class RegisterRulesTest { repo.done(); }); - RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RuleKey.of(repository1, ruleKey)); + RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RuleKey.of(repository1, ruleKey)); SearchIdResult searchRule1 = ruleIndex.search(new RuleQuery().setQueryText("Name1"), new SearchOptions()); assertThat(searchRule1.getIds()).containsOnly(rule1.getId()); assertThat(searchRule1.getTotal()).isEqualTo(1); @@ -522,7 +526,7 @@ public class RegisterRulesTest { }); // rule2 is actually rule1 - RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RuleKey.of(repository2, ruleKey)); + RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RuleKey.of(repository2, ruleKey)); assertThat(rule2.getId()).isEqualTo(rule1.getId()); assertThat(rule2.getName()).isEqualTo("Name2"); assertThat(rule2.getDescription()).isEqualTo(rule1.getDescription()); @@ -547,7 +551,7 @@ public class RegisterRulesTest { repo.done(); }); - RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RuleKey.of(repo1, ruleKey1)); + RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RuleKey.of(repo1, ruleKey1)); assertThat(ruleIndex.search(new RuleQuery().setQueryText(name), new SearchOptions()).getIds()) .containsOnly(rule1.getId()); @@ -562,7 +566,7 @@ public class RegisterRulesTest { }); // rule2 is actually rule1 - RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RuleKey.of(repo2, ruleKey2)); + RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RuleKey.of(repo2, ruleKey2)); assertThat(rule2.getId()).isEqualTo(rule1.getId()); assertThat(rule2.getName()).isEqualTo(rule1.getName()); assertThat(rule2.getDescription()).isEqualTo(rule1.getDescription()); @@ -596,7 +600,7 @@ public class RegisterRulesTest { repo.done(); }); - RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RuleKey.of(repository1, ruleKey1)); + RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RuleKey.of(repository1, ruleKey1)); assertThat(ruleIndex.search(new RuleQuery().setQueryText("Name1"), new SearchOptions()).getIds()) .containsOnly(rule1.getId()); @@ -613,7 +617,7 @@ public class RegisterRulesTest { }); // rule2 is actually rule1 - RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RuleKey.of(repository2, ruleKey2)); + RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RuleKey.of(repository2, ruleKey2)); assertThat(rule2.getId()).isEqualTo(rule1.getId()); assertThat(ruleIndex.search(new RuleQuery().setQueryText("Name2"), new SearchOptions()).getIds()) @@ -641,7 +645,7 @@ public class RegisterRulesTest { }); // rule1 has been updated - RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RuleKey.of("fake", "rule")); + RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RuleKey.of("fake", "rule")); assertThat(rule1.getName()).isEqualTo("Name"); assertThat(rule1.getDescription()).isEqualTo("Desc2"); @@ -649,6 +653,48 @@ public class RegisterRulesTest { assertThat(ruleIndex.search(new RuleQuery().setQueryText("Desc1"), new SearchOptions()).getTotal()).isEqualTo(0); } + @Test + public void rule_previously_created_as_adhoc_becomes_none_adhoc() { + RuleDefinitionDto rule = db.rules().insert(r -> r.setRepositoryKey("external_fake").setIsExternal(true).setIsAdHoc(true)); + when(system.now()).thenReturn(DATE2.getTime()); + execute((RulesDefinition) context -> { + NewRepository repo = context.createExternalRepository("fake", rule.getLanguage()); + repo.createRule(rule.getRuleKey()) + .setName(rule.getName()) + .setHtmlDescription(rule.getDescription()); + repo.done(); + }); + + RuleDto reloaded = dbClient.ruleDao().selectByKey(db.getSession(), defaultOrganization, rule.getKey()).get(); + assertThat(reloaded.isAdHoc()).isFalse(); + } + + @Test + public void remove_no_more_defined_external_rule() { + RuleDefinitionDto rule = db.rules().insert(r -> r.setRepositoryKey("external_fake") + .setStatus(READY) + .setIsExternal(true) + .setIsAdHoc(false)); + + execute(); + + RuleDto reloaded = dbClient.ruleDao().selectByKey(db.getSession(), defaultOrganization, rule.getKey()).get(); + assertThat(reloaded.getStatus()).isEqualTo(REMOVED); + } + + @Test + public void do_not_remove_no_more_defined_ad_hoc_rule() { + RuleDefinitionDto rule = db.rules().insert(r -> r.setRepositoryKey("external_fake") + .setStatus(READY) + .setIsExternal(true) + .setIsAdHoc(true)); + + execute(); + + RuleDto reloaded = dbClient.ruleDao().selectByKey(db.getSession(), defaultOrganization, rule.getKey()).get(); + assertThat(reloaded.getStatus()).isEqualTo(READY); + } + @Test public void disable_then_enable_rule() { // Install rule @@ -659,15 +705,15 @@ public class RegisterRulesTest { when(system.now()).thenReturn(DATE2.getTime()); execute(); - RuleDto rule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1); - assertThat(rule.getStatus()).isEqualTo(RuleStatus.REMOVED); + RuleDto rule = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY1); + assertThat(rule.getStatus()).isEqualTo(REMOVED); assertThat(ruleIndex.search(new RuleQuery().setKey(RULE_KEY1.toString()), new SearchOptions()).getTotal()).isEqualTo(0); // Re-install rule when(system.now()).thenReturn(DATE3.getTime()); execute(new FakeRepositoryV1()); - rule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1); + rule = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY1); assertThat(rule.getStatus()).isEqualTo(RuleStatus.BETA); assertThat(ruleIndex.search(new RuleQuery().setKey(RULE_KEY1.toString()), new SearchOptions()).getTotal()).isEqualTo(1); } @@ -675,12 +721,12 @@ public class RegisterRulesTest { @Test public void do_not_update_rules_when_no_changes() { execute(new FakeRepositoryV1()); - assertThat(dbClient.ruleDao().selectAllDefinitions(dbTester.getSession())).hasSize(3); + assertThat(dbClient.ruleDao().selectAllDefinitions(db.getSession())).hasSize(3); when(system.now()).thenReturn(DATE2.getTime()); execute(new FakeRepositoryV1()); - RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1); + RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY1); assertThat(rule1.getCreatedAt()).isEqualTo(DATE1.getTime()); assertThat(rule1.getUpdatedAt()).isEqualTo(DATE1.getTime()); } @@ -688,36 +734,36 @@ public class RegisterRulesTest { @Test public void do_not_update_already_removed_rules() { execute(new FakeRepositoryV1()); - assertThat(dbClient.ruleDao().selectAllDefinitions(dbTester.getSession())).hasSize(3); + assertThat(dbClient.ruleDao().selectAllDefinitions(db.getSession())).hasSize(3); - RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1); - RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY2); - RuleDto hotspotRule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, HOTSPOT_RULE_KEY); + RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY1); + RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY2); + RuleDto hotspotRule = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, HOTSPOT_RULE_KEY); assertThat(es.getIds(RuleIndexDefinition.INDEX_TYPE_RULE)).containsOnly(valueOf(rule1.getId()), valueOf(rule2.getId()), valueOf(hotspotRule.getId())); - assertThat(rule2.getStatus()).isEqualTo(RuleStatus.READY); + assertThat(rule2.getStatus()).isEqualTo(READY); when(system.now()).thenReturn(DATE2.getTime()); execute(new FakeRepositoryV2()); // On MySQL, need to update a rule otherwise rule2 will be seen as READY, but why ??? - dbClient.ruleDao().update(dbTester.getSession(), rule1.getDefinition()); - dbTester.getSession().commit(); + dbClient.ruleDao().update(db.getSession(), rule1.getDefinition()); + db.getSession().commit(); // rule2 is removed - rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY2); - RuleDto rule3 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY3); - assertThat(rule2.getStatus()).isEqualTo(RuleStatus.REMOVED); + rule2 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY2); + RuleDto rule3 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY3); + assertThat(rule2.getStatus()).isEqualTo(REMOVED); assertThat(ruleIndex.search(new RuleQuery(), new SearchOptions()).getIds()).containsOnly(rule1.getId(), rule3.getId()); when(system.now()).thenReturn(DATE3.getTime()); execute(new FakeRepositoryV2()); - dbTester.getSession().commit(); + db.getSession().commit(); // -> rule2 is still removed, but not update at DATE3 - rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY2); - assertThat(rule2.getStatus()).isEqualTo(RuleStatus.REMOVED); + rule2 = dbClient.ruleDao().selectOrFailByKey(db.getSession(), defaultOrganization, RULE_KEY2); + assertThat(rule2.getStatus()).isEqualTo(REMOVED); assertThat(rule2.getUpdatedAt()).isEqualTo(DATE2.getTime()); assertThat(ruleIndex.search(new RuleQuery(), new SearchOptions()).getIds()).containsOnly(rule1.getId(), rule3.getId()); @@ -726,15 +772,15 @@ public class RegisterRulesTest { @Test public void mass_insert() { execute(new BigRepository()); - assertThat(dbTester.countRowsOfTable("rules")).isEqualTo(BigRepository.SIZE); - assertThat(dbTester.countRowsOfTable("rules_parameters")).isEqualTo(BigRepository.SIZE * 20); + assertThat(db.countRowsOfTable("rules")).isEqualTo(BigRepository.SIZE); + assertThat(db.countRowsOfTable("rules_parameters")).isEqualTo(BigRepository.SIZE * 20); assertThat(es.getIds(RuleIndexDefinition.INDEX_TYPE_RULE)).hasSize(BigRepository.SIZE); } @Test public void manage_repository_extensions() { execute(new FindbugsRepository(), new FbContribRepository()); - List rules = dbClient.ruleDao().selectAllDefinitions(dbTester.getSession()); + List rules = dbClient.ruleDao().selectAllDefinitions(db.getSession()); assertThat(rules).hasSize(2); for (RuleDefinitionDto rule : rules) { assertThat(rule.getRepositoryKey()).isEqualTo("findbugs"); @@ -744,7 +790,7 @@ public class RegisterRulesTest { @Test public void remove_system_tags_when_plugin_does_not_provide_any() { // Rule already exists in DB, with some system tags - dbClient.ruleDao().insert(dbTester.getSession(), new RuleDefinitionDto() + dbClient.ruleDao().insert(db.getSession(), new RuleDefinitionDto() .setRuleKey("rule1") .setRepositoryKey("findbugs") .setName("Rule One") @@ -752,12 +798,12 @@ public class RegisterRulesTest { .setDescription("Rule one description") .setDescriptionFormat(RuleDto.Format.HTML) .setSystemTags(newHashSet("tag1", "tag2"))); - dbTester.getSession().commit(); + db.getSession().commit(); // Synchronize rule without tag execute(new FindbugsRepository()); - List rules = dbClient.ruleDao().selectAllDefinitions(dbTester.getSession()); + List rules = dbClient.ruleDao().selectAllDefinitions(db.getSession()); assertThat(rules).hasSize(1); RuleDefinitionDto result = rules.get(0); assertThat(result.getKey()).isEqualTo(RuleKey.of("findbugs", "rule1")); @@ -766,16 +812,16 @@ public class RegisterRulesTest { @Test public void ignore_template_rules_if_organizations_are_enabled() { - organizationFlags.enable(dbTester.getSession()); + organizationFlags.enable(db.getSession()); execute(new RepositoryWithOneTemplateRule()); - List rules = dbClient.ruleDao().selectAllDefinitions(dbTester.getSession()); + List rules = dbClient.ruleDao().selectAllDefinitions(db.getSession()); assertThat(rules).hasSize(0); } @Test public void log_ignored_template_rules_if_organizations_are_enabled() { - organizationFlags.enable(dbTester.getSession()); + organizationFlags.enable(db.getSession()); execute(new RepositoryWithOneTemplateRule()); assertThat(logTester.logs(LoggerLevel.INFO)).contains("Template rule test:rule1 will not be imported, because organizations are enabled."); @@ -811,8 +857,8 @@ public class RegisterRulesTest { repo.done(); }); - List rules = dbClient.ruleDao().selectAllDefinitions(dbTester.getSession()); - Set deprecatedRuleKeys = dbClient.ruleDao().selectAllDeprecatedRuleKeys(dbTester.getSession()); + List rules = dbClient.ruleDao().selectAllDefinitions(db.getSession()); + Set deprecatedRuleKeys = dbClient.ruleDao().selectAllDeprecatedRuleKeys(db.getSession()); assertThat(rules).hasSize(1); assertThat(deprecatedRuleKeys).hasSize(2); } @@ -847,8 +893,8 @@ public class RegisterRulesTest { repo.done(); }); - assertThat(dbClient.ruleDao().selectAllDefinitions(dbTester.getSession())).hasSize(1); - Set deprecatedRuleKeys = dbClient.ruleDao().selectAllDeprecatedRuleKeys(dbTester.getSession()); + assertThat(dbClient.ruleDao().selectAllDefinitions(db.getSession())).hasSize(1); + Set deprecatedRuleKeys = dbClient.ruleDao().selectAllDeprecatedRuleKeys(db.getSession()); assertThat(deprecatedRuleKeys).hasSize(2); execute(context -> { @@ -864,8 +910,8 @@ public class RegisterRulesTest { repo.done(); }); - assertThat(dbClient.ruleDao().selectAllDefinitions(dbTester.getSession())).hasSize(1); - deprecatedRuleKeys = dbClient.ruleDao().selectAllDeprecatedRuleKeys(dbTester.getSession()); + assertThat(dbClient.ruleDao().selectAllDefinitions(db.getSession())).hasSize(1); + deprecatedRuleKeys = dbClient.ruleDao().selectAllDeprecatedRuleKeys(db.getSession()); assertThat(deprecatedRuleKeys).hasSize(0); } @@ -984,7 +1030,7 @@ public class RegisterRulesTest { languages, system, organizationFlags, webServerRuleFinder, uuidFactory); task.start(); // Execute a commit to refresh session state as the task is using its own session - dbTester.getSession().commit(); + db.getSession().commit(); verify(webServerRuleFinder).startCaching(); } @@ -1062,7 +1108,7 @@ public class RegisterRulesTest { // tag2 and tag3 removed, tag4 added .setTags("tag1", "tag4") .setType(RuleType.BUG) - .setStatus(RuleStatus.READY) + .setStatus(READY) .setGapDescription("squid.S115.effortToFix.v2"); rule1.setDebtRemediationFunction(rule1.debtRemediationFunctions().linearWithOffset("6d", "2h")); rule1.createParam("param1").setDescription("parameter one v2").setDefaultValue("default1 v2"); diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorTest.java index 4dff170b40e..fb11ffa0bf0 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorTest.java @@ -104,6 +104,8 @@ public class RuleCreatorTest { assertThat(rule.getTags()).containsOnly("usertag1", "usertag2"); assertThat(rule.getSystemTags()).containsOnly("tag1", "tag4"); assertThat(rule.getSecurityStandards()).containsOnly("owaspTop10:a1", "cwe:123"); + assertThat(rule.isExternal()).isFalse(); + assertThat(rule.isAdHoc()).isFalse(); List params = dbTester.getDbClient().ruleDao().selectRuleParamsByRuleKey(dbSession, customRuleKey); assertThat(params).hasSize(1); diff --git a/server/sonar-server/src/test/resources/org/sonar/server/platform/BackendCleanupTest/shared.xml b/server/sonar-server/src/test/resources/org/sonar/server/platform/BackendCleanupTest/shared.xml index 2607915bf61..63b66538ca9 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/platform/BackendCleanupTest/shared.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/platform/BackendCleanupTest/shared.xml @@ -42,6 +42,8 @@ def_remediation_base_effort="10h" gap_description="squid.S115.effortToFix" description_format="MARKDOWN" + is_external="[false]" + is_ad_hoc="[false]" created_at="150000" updated_at="150000" scope="MAIN" -- 2.39.5