From: Julien Lancelot Date: Fri, 14 Apr 2017 16:11:54 +0000 (+0200) Subject: SONAR-9013 Remove usage of ServerTester in RuleUpdaterMediumTest X-Git-Tag: 6.4-RC1~344 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=4df60a42ed232f82c6c97c00296c4dbb8ac4398e;p=sonarqube.git SONAR-9013 Remove usage of ServerTester in RuleUpdaterMediumTest --- diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java deleted file mode 100644 index 6db295282ef..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java +++ /dev/null @@ -1,625 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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.rule; - -import com.google.common.base.Function; -import com.google.common.collect.FluentIterable; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; -import java.util.List; -import java.util.Map; -import javax.annotation.Nonnull; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rule.RuleStatus; -import org.sonar.api.rule.Severity; -import org.sonar.api.server.debt.DebtRemediationFunction; -import org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.organization.OrganizationDto; -import org.sonar.db.qualityprofile.ActiveRuleDto; -import org.sonar.db.qualityprofile.ActiveRuleKey; -import org.sonar.db.qualityprofile.ActiveRuleParamDto; -import org.sonar.db.qualityprofile.QualityProfileDto; -import org.sonar.db.rule.RuleDao; -import org.sonar.db.rule.RuleDefinitionDto; -import org.sonar.db.rule.RuleDto; -import org.sonar.db.rule.RuleParamDto; -import org.sonar.db.rule.RuleTesting; -import org.sonar.server.es.SearchOptions; -import org.sonar.server.organization.DefaultOrganizationProvider; -import org.sonar.server.qualityprofile.QProfileTesting; -import org.sonar.server.qualityprofile.RuleActivation; -import org.sonar.server.qualityprofile.RuleActivator; -import org.sonar.server.rule.index.RuleIndex; -import org.sonar.server.rule.index.RuleQuery; -import org.sonar.server.tester.ServerTester; -import org.sonar.server.tester.UserSessionRule; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; - -// TODO remove ServerTester usage when ActiveRule Daov2 is removed -public class RuleUpdaterMediumTest { - - static final RuleKey RULE_KEY = RuleKey.of("squid", "S001"); - - @ClassRule - public static ServerTester tester = new ServerTester().withEsIndexes(); - - @org.junit.Rule - public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester); - - private DbClient db = tester.get(DbClient.class); - private RuleDao ruleDao = tester.get(RuleDao.class); - private DbSession dbSession = db.openSession(false); - private RuleIndex ruleIndex = tester.get(RuleIndex.class); - private OrganizationDto defaultOrganization; - - RuleUpdater underTest = tester.get(RuleUpdater.class); - - @Before - public void before() { - tester.clearDbAndIndexes(); - String defaultOrganizationUuid = tester.get(DefaultOrganizationProvider.class).get().getUuid(); - defaultOrganization = db.organizationDao().selectByUuid(dbSession, defaultOrganizationUuid).get(); - } - - @After - public void after() { - dbSession.close(); - } - - @Test - public void do_not_update_rule_with_removed_status() { - ruleDao.insert(dbSession, RuleTesting.newRule(RULE_KEY).setStatus(RuleStatus.REMOVED)); - dbSession.commit(); - - RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) - .setTags(Sets.newHashSet("java9")) - .setOrganization(defaultOrganization); - try { - underTest.update(dbSession, update, defaultOrganization, userSessionRule); - fail(); - } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Rule with REMOVED status cannot be updated: squid:S001"); - } - } - - @Test - public void no_changes() { - RuleDto ruleDto = RuleTesting.newDto(RULE_KEY, defaultOrganization) - // the following fields are not supposed to be updated - .setNoteData("my *note*") - .setNoteUserLogin("me") - .setTags(ImmutableSet.of("tag1")) - .setRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()) - .setRemediationGapMultiplier("1d") - .setRemediationBaseEffort("5min"); - ruleDao.insert(dbSession, ruleDto.getDefinition()); - ruleDao.insertOrUpdate(dbSession, ruleDto.getMetadata().setRuleId(ruleDto.getId())); - dbSession.commit(); - - RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY); - assertThat(update.isEmpty()).isTrue(); - underTest.update(dbSession, update, defaultOrganization, userSessionRule); - - dbSession.clearCache(); - RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY); - assertThat(rule.getNoteData()).isEqualTo("my *note*"); - assertThat(rule.getNoteUserLogin()).isEqualTo("me"); - assertThat(rule.getTags()).containsOnly("tag1"); - assertThat(rule.getRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()); - assertThat(rule.getRemediationGapMultiplier()).isEqualTo("1d"); - assertThat(rule.getRemediationBaseEffort()).isEqualTo("5min"); - } - - @Test - public void set_markdown_note() { - userSessionRule.logIn("me"); - - RuleDto ruleDto = RuleTesting.newDto(RULE_KEY, defaultOrganization) - .setNoteData(null) - .setNoteUserLogin(null) - - // the following fields are not supposed to be updated - .setTags(ImmutableSet.of("tag1")) - .setRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()) - .setRemediationGapMultiplier("1d") - .setRemediationBaseEffort("5min"); - ruleDao.insert(dbSession, ruleDto.getDefinition()); - ruleDao.insertOrUpdate(dbSession, ruleDto.getMetadata().setRuleId(ruleDto.getId())); - dbSession.commit(); - - RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) - .setMarkdownNote("my *note*") - .setOrganization(defaultOrganization); - underTest.update(dbSession, update, defaultOrganization, userSessionRule); - - dbSession.clearCache(); - RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY); - assertThat(rule.getNoteData()).isEqualTo("my *note*"); - assertThat(rule.getNoteUserLogin()).isEqualTo("me"); - assertThat(rule.getNoteCreatedAt()).isNotNull(); - assertThat(rule.getNoteUpdatedAt()).isNotNull(); - // no other changes - assertThat(rule.getTags()).containsOnly("tag1"); - assertThat(rule.getRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()); - assertThat(rule.getRemediationGapMultiplier()).isEqualTo("1d"); - assertThat(rule.getRemediationBaseEffort()).isEqualTo("5min"); - } - - @Test - public void remove_markdown_note() { - RuleDto ruleDto = RuleTesting.newDto(RULE_KEY, defaultOrganization) - .setNoteData("my *note*") - .setNoteUserLogin("me"); - ruleDao.insert(dbSession, ruleDto.getDefinition()); - ruleDao.insertOrUpdate(dbSession, ruleDto.getMetadata().setRuleId(ruleDto.getId())); - dbSession.commit(); - - RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) - .setMarkdownNote(null) - .setOrganization(defaultOrganization); - underTest.update(dbSession, update, defaultOrganization, userSessionRule); - - dbSession.clearCache(); - RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY); - assertThat(rule.getNoteData()).isNull(); - assertThat(rule.getNoteUserLogin()).isNull(); - assertThat(rule.getNoteCreatedAt()).isNull(); - assertThat(rule.getNoteUpdatedAt()).isNull(); - } - - @Test - public void set_tags() { - // insert db - ruleDao.insert(dbSession, RuleTesting.newDto(RULE_KEY, defaultOrganization) - .setTags(Sets.newHashSet("security")) - .setSystemTags(Sets.newHashSet("java8", "javadoc")).getDefinition()); - dbSession.commit(); - - // java8 is a system tag -> ignore - RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) - .setTags(Sets.newHashSet("bug", "java8")) - .setOrganization(defaultOrganization); - underTest.update(dbSession, update, defaultOrganization, userSessionRule); - - RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY); - assertThat(rule.getTags()).containsOnly("bug"); - assertThat(rule.getSystemTags()).containsOnly("java8", "javadoc"); - - // verify that tags are indexed in index - List tags = ruleIndex.listTags(defaultOrganization, null, 10); - assertThat(tags).containsExactly("bug", "java8", "javadoc"); - } - - @Test - public void remove_tags() { - RuleDto ruleDto = RuleTesting.newDto(RULE_KEY, defaultOrganization) - .setTags(Sets.newHashSet("security")) - .setSystemTags(Sets.newHashSet("java8", "javadoc")); - ruleDao.insert(dbSession, ruleDto.getDefinition()); - ruleDao.insertOrUpdate(dbSession, ruleDto.getMetadata()); - dbSession.commit(); - - RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) - .setTags(null) - .setOrganization(defaultOrganization); - underTest.update(dbSession, update, defaultOrganization, userSessionRule); - - dbSession.clearCache(); - RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY); - assertThat(rule.getTags()).isEmpty(); - assertThat(rule.getSystemTags()).containsOnly("java8", "javadoc"); - - // verify that tags are indexed in index - List tags = ruleIndex.listTags(defaultOrganization, null, 10); - assertThat(tags).containsExactly("java8", "javadoc"); - } - - @Test - public void override_debt() { - ruleDao.insert(dbSession, RuleTesting.newRule(RULE_KEY) - .setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setDefRemediationGapMultiplier("1d") - .setDefRemediationBaseEffort("5min")); - dbSession.commit(); - - DefaultDebtRemediationFunction fn = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, null, "1min"); - RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) - .setDebtRemediationFunction(fn) - .setOrganization(defaultOrganization); - underTest.update(dbSession, update, defaultOrganization, userSessionRule); - dbSession.clearCache(); - - // verify debt is overridden - RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY); - assertThat(rule.getRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()); - assertThat(rule.getRemediationGapMultiplier()).isNull(); - assertThat(rule.getRemediationBaseEffort()).isEqualTo("1min"); - - assertThat(rule.getDefRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET.name()); - assertThat(rule.getDefRemediationGapMultiplier()).isEqualTo("1d"); - assertThat(rule.getDefRemediationBaseEffort()).isEqualTo("5min"); - } - - @Test - public void override_debt_only_offset() { - ruleDao.insert(dbSession, RuleTesting.newRule(RULE_KEY) - .setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR.name()) - .setDefRemediationGapMultiplier("1d") - .setDefRemediationBaseEffort(null)); - dbSession.commit(); - - RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) - .setDebtRemediationFunction(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, "2d", null)) - .setOrganization(defaultOrganization); - underTest.update(dbSession, update, defaultOrganization, userSessionRule); - dbSession.clearCache(); - - // verify debt is overridden - RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY); - assertThat(rule.getRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.LINEAR.name()); - assertThat(rule.getRemediationGapMultiplier()).isEqualTo("2d"); - assertThat(rule.getRemediationBaseEffort()).isNull(); - - assertThat(rule.getDefRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.LINEAR.name()); - assertThat(rule.getDefRemediationGapMultiplier()).isEqualTo("1d"); - assertThat(rule.getDefRemediationBaseEffort()).isNull(); - } - - @Test - public void override_debt_from_linear_with_offset_to_constant() { - ruleDao.insert(dbSession, RuleTesting.newRule(RULE_KEY) - .setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setDefRemediationGapMultiplier("1d") - .setDefRemediationBaseEffort("5min")); - dbSession.commit(); - - RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) - .setDebtRemediationFunction(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, null, "10min")) - .setOrganization(defaultOrganization); - underTest.update(dbSession, update, defaultOrganization, userSessionRule); - dbSession.clearCache(); - - // verify debt is overridden - RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY); - assertThat(rule.getRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()); - assertThat(rule.getRemediationGapMultiplier()).isNull(); - assertThat(rule.getRemediationBaseEffort()).isEqualTo("10min"); - - assertThat(rule.getDefRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET.name()); - assertThat(rule.getDefRemediationGapMultiplier()).isEqualTo("1d"); - assertThat(rule.getDefRemediationBaseEffort()).isEqualTo("5min"); - } - - @Test - public void reset_remediation_function() { - RuleDto ruleDto = RuleTesting.newDto(RULE_KEY, defaultOrganization) - .setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR.name()) - .setDefRemediationGapMultiplier("1d") - .setDefRemediationBaseEffort("5min") - .setRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()) - .setRemediationGapMultiplier(null) - .setRemediationBaseEffort("1min"); - ruleDao.insert(dbSession, ruleDto.getDefinition()); - ruleDao.insertOrUpdate(dbSession, ruleDto.getMetadata().setRuleId(ruleDto.getId())); - dbSession.commit(); - - RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) - .setDebtRemediationFunction(null) - .setOrganization(defaultOrganization); - underTest.update(dbSession, update, defaultOrganization, userSessionRule); - dbSession.clearCache(); - - // verify debt is coming from default values - RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY); - assertThat(rule.getDefRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.LINEAR.name()); - assertThat(rule.getDefRemediationGapMultiplier()).isEqualTo("1d"); - assertThat(rule.getDefRemediationBaseEffort()).isEqualTo("5min"); - - assertThat(rule.getRemediationFunction()).isNull(); - assertThat(rule.getRemediationGapMultiplier()).isNull(); - assertThat(rule.getRemediationBaseEffort()).isNull(); - } - - @Test - public void update_custom_rule() { - // Create template rule - RuleDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001")); - ruleDao.insert(dbSession, templateRule.getDefinition()); - RuleParamDto templateRuleParam1 = RuleParamDto.createFor(templateRule.getDefinition()).setName("regex").setType("STRING").setDescription("Reg ex").setDefaultValue(".*"); - RuleParamDto templateRuleParam2 = RuleParamDto.createFor(templateRule.getDefinition()).setName("format").setType("STRING").setDescription("Format"); - ruleDao.insertRuleParam(dbSession, templateRule.getDefinition(), templateRuleParam1); - ruleDao.insertRuleParam(dbSession, templateRule.getDefinition(), templateRuleParam2); - - // Create custom rule - RuleDefinitionDto customRule = RuleTesting.newCustomRule(templateRule) - .setName("Old name") - .setDescription("Old description") - .setSeverity(Severity.MINOR) - .setStatus(RuleStatus.BETA) - .getDefinition(); - ruleDao.insert(dbSession, customRule); - ruleDao.insertRuleParam(dbSession, customRule, templateRuleParam1.setDefaultValue("a.*")); - ruleDao.insertRuleParam(dbSession, customRule, templateRuleParam2.setDefaultValue(null)); - - dbSession.commit(); - - // Update custom rule - RuleUpdate update = RuleUpdate.createForCustomRule(customRule.getKey()) - .setName("New name") - .setMarkdownDescription("New description") - .setSeverity("MAJOR") - .setStatus(RuleStatus.READY) - .setParameters(ImmutableMap.of("regex", "b.*")) - .setOrganization(defaultOrganization); - underTest.update(dbSession, update, defaultOrganization, userSessionRule); - - dbSession.clearCache(); - - // Verify custom rule is updated - RuleDto customRuleReloaded = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, customRule.getKey()); - assertThat(customRuleReloaded).isNotNull(); - assertThat(customRuleReloaded.getName()).isEqualTo("New name"); - assertThat(customRuleReloaded.getDescription()).isEqualTo("New description"); - assertThat(customRuleReloaded.getSeverityString()).isEqualTo("MAJOR"); - assertThat(customRuleReloaded.getStatus()).isEqualTo(RuleStatus.READY); - - List params = ruleDao.selectRuleParamsByRuleKey(dbSession, customRuleReloaded.getKey()); - assertThat(params).hasSize(2); - assertThat(params.get(0).getDefaultValue()).isEqualTo("b.*"); - assertThat(params.get(1).getDefaultValue()).isNull(); - - // Verify in index - assertThat(ruleIndex.search(new RuleQuery().setQueryText("New name"), new SearchOptions()).getIds()).containsOnly(customRule.getKey()); - assertThat(ruleIndex.search(new RuleQuery().setQueryText("New description"), new SearchOptions()).getIds()).containsOnly(customRule.getKey()); - - assertThat(ruleIndex.search(new RuleQuery().setQueryText("Old name"), new SearchOptions()).getTotal()).isZero(); - assertThat(ruleIndex.search(new RuleQuery().setQueryText("Old description"), new SearchOptions()).getTotal()).isZero(); - } - - @Test - public void update_custom_rule_with_empty_parameter() { - // Create template rule - RuleDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001")); - ruleDao.insert(dbSession, templateRule.getDefinition()); - RuleParamDto templateRuleParam = RuleParamDto.createFor(templateRule.getDefinition()).setName("regex").setType("STRING").setDescription("Reg ex"); - ruleDao.insertRuleParam(dbSession, templateRule.getDefinition(), templateRuleParam); - - // Create custom rule - RuleDefinitionDto customRule = RuleTesting.newCustomRule(templateRule) - .setName("Old name") - .setDescription("Old description") - .setSeverity(Severity.MINOR) - .setStatus(RuleStatus.BETA) - .getDefinition(); - ruleDao.insert(dbSession, customRule); - ruleDao.insertRuleParam(dbSession, customRule, templateRuleParam); - - dbSession.commit(); - - // Update custom rule without setting a value for the parameter - RuleUpdate update = RuleUpdate.createForCustomRule(customRule.getKey()) - .setName("New name") - .setMarkdownDescription("New description") - .setSeverity("MAJOR") - .setStatus(RuleStatus.READY) - .setOrganization(defaultOrganization); - underTest.update(dbSession, update, defaultOrganization, userSessionRule); - - dbSession.clearCache(); - - // Verify custom rule is updated - List params = ruleDao.selectRuleParamsByRuleKey(dbSession, customRule.getKey()); - assertThat(params.get(0).getDefaultValue()).isNull(); - } - - @Test - public void update_active_rule_parameters_when_updating_custom_rule() { - // Create template rule with 3 parameters - RuleDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001")).setLanguage("xoo"); - RuleDefinitionDto templateRuleDefinition = templateRule.getDefinition(); - ruleDao.insert(dbSession, templateRuleDefinition); - RuleParamDto templateRuleParam1 = RuleParamDto.createFor(templateRuleDefinition).setName("regex").setType("STRING").setDescription("Reg ex").setDefaultValue(".*"); - ruleDao.insertRuleParam(dbSession, templateRuleDefinition, templateRuleParam1); - RuleParamDto templateRuleParam2 = RuleParamDto.createFor(templateRuleDefinition).setName("format").setType("STRING").setDescription("format").setDefaultValue("csv"); - ruleDao.insertRuleParam(dbSession, templateRuleDefinition, templateRuleParam2); - RuleParamDto templateRuleParam3 = RuleParamDto.createFor(templateRuleDefinition).setName("message").setType("STRING").setDescription("message"); - ruleDao.insertRuleParam(dbSession, templateRuleDefinition, templateRuleParam3); - - // Create custom rule - RuleDefinitionDto customRule = RuleTesting.newCustomRule(templateRule) - .setSeverity(Severity.MAJOR) - .setLanguage("xoo") - .getDefinition(); - ruleDao.insert(dbSession, customRule); - ruleDao.insertRuleParam(dbSession, customRule, templateRuleParam1.setDefaultValue("a.*")); - ruleDao.insertRuleParam(dbSession, customRule, templateRuleParam2.setDefaultValue("txt")); - ruleDao.insertRuleParam(dbSession, customRule, templateRuleParam3); - - // Create a quality profile - QualityProfileDto profileDto = QProfileTesting.newXooP1(defaultOrganization); - db.qualityProfileDao().insert(dbSession, profileDto); - dbSession.commit(); - - // Activate the custom rule - RuleActivation activation = new RuleActivation(customRule.getKey()).setSeverity(Severity.BLOCKER); - tester.get(RuleActivator.class).activate(dbSession, activation, profileDto); - dbSession.commit(); - dbSession.clearCache(); - - // Update custom rule parameter 'regex', add 'message' and remove 'format' - RuleUpdate update = RuleUpdate.createForCustomRule(customRule.getKey()) - .setParameters(ImmutableMap.of("regex", "b.*", "message", "a message")) - .setOrganization(defaultOrganization); - underTest.update(dbSession, update, defaultOrganization, userSessionRule); - - dbSession.clearCache(); - - // Verify custom rule parameters has been updated - List params = ruleDao.selectRuleParamsByRuleKey(dbSession, customRule.getKey()); - assertThat(params).hasSize(3); - - Map paramsByKey = paramsByKey(params); - assertThat(paramsByKey.get("regex")).isNotNull(); - assertThat(paramsByKey.get("regex").getDefaultValue()).isEqualTo("b.*"); - assertThat(paramsByKey.get("message")).isNotNull(); - assertThat(paramsByKey.get("message").getDefaultValue()).isEqualTo("a message"); - assertThat(paramsByKey.get("format")).isNotNull(); - assertThat(paramsByKey.get("format").getDefaultValue()).isNull(); - - // Verify that severity has not changed - ActiveRuleDto activeRuleDto = db.activeRuleDao().selectOrFailByKey(dbSession, ActiveRuleKey.of(profileDto.getKey(), customRule.getKey())); - assertThat(activeRuleDto.getSeverityString()).isEqualTo(Severity.BLOCKER); - - // Verify active rule parameters has been updated - List activeRuleParams = db.activeRuleDao().selectParamsByActiveRuleId(dbSession, activeRuleDto.getId()); - - assertThat(activeRuleParams).hasSize(2); - Map activeRuleParamsByKey = ActiveRuleParamDto.groupByKey(activeRuleParams); - assertThat(activeRuleParamsByKey.get("regex").getValue()).isEqualTo("b.*"); - assertThat(activeRuleParamsByKey.get("message").getValue()).isEqualTo("a message"); - assertThat(activeRuleParamsByKey.get("format")).isNull(); - } - - @Test - public void fail_to_update_custom_rule_when_empty_name() { - // Create template rule - RuleDefinitionDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001")).getDefinition(); - ruleDao.insert(dbSession, templateRule); - - // Create custom rule - RuleDefinitionDto customRule = RuleTesting.newCustomRule(templateRule); - ruleDao.insert(dbSession, customRule); - - dbSession.commit(); - - // Update custom rule - RuleUpdate update = RuleUpdate.createForCustomRule(customRule.getKey()) - .setName("") - .setMarkdownDescription("New desc") - .setOrganization(defaultOrganization); - try { - underTest.update(dbSession, update, defaultOrganization, userSessionRule); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("The name is missing"); - } - } - - @Test - public void fail_to_update_custom_rule_when_empty_description() { - // Create template rule - RuleDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001")); - ruleDao.insert(dbSession, templateRule.getDefinition()); - - // Create custom rule - RuleDto customRule = RuleTesting.newCustomRule(templateRule); - ruleDao.insert(dbSession, customRule.getDefinition()); - - dbSession.commit(); - - // Update custom rule - RuleUpdate update = RuleUpdate.createForCustomRule(customRule.getKey()) - .setName("New name") - .setMarkdownDescription("") - .setOrganization(defaultOrganization); - try { - underTest.update(dbSession, update, defaultOrganization, userSessionRule); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("The description is missing"); - } - } - - @Test - public void fail_to_update_plugin_rule_if_name_is_set() { - // Create rule rule - RuleDefinitionDto ruleDto = RuleTesting.newRule(RuleKey.of("squid", "S01")); - ruleDao.insert(dbSession, ruleDto); - - dbSession.commit(); - - try { - // Update rule - RuleUpdate.createForPluginRule(ruleDto.getKey()) - .setName("New name"); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not a custom rule"); - } - } - - @Test - public void fail_to_update_plugin_rule_if_description_is_set() { - // Create rule rule - RuleDefinitionDto ruleDto = RuleTesting.newRule(RuleKey.of("squid", "S01")); - ruleDao.insert(dbSession, ruleDto); - - dbSession.commit(); - - try { - // Update rule - RuleUpdate.createForPluginRule(ruleDto.getKey()) - .setMarkdownDescription("New description"); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not a custom rule"); - } - } - - @Test - public void fail_to_update_plugin_rule_if_severity_is_set() { - // Create rule rule - RuleDefinitionDto ruleDto = RuleTesting.newRule(RuleKey.of("squid", "S01")); - ruleDao.insert(dbSession, ruleDto); - - dbSession.commit(); - - try { - // Update rule - RuleUpdate.createForPluginRule(ruleDto.getKey()) - .setSeverity(Severity.CRITICAL); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not a custom rule"); - } - } - - private static Map paramsByKey(List params) { - return FluentIterable.from(params).uniqueIndex(RuleParamToKey.INSTANCE); - } - - private enum RuleParamToKey implements Function { - INSTANCE; - - @Override - public String apply(@Nonnull RuleParamDto input) { - return input.getName(); - } - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterTest.java new file mode 100644 index 00000000000..2987f0eb0cd --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterTest.java @@ -0,0 +1,614 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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.rule; + +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import java.util.List; +import java.util.Map; +import javax.annotation.Nonnull; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.config.MapSettings; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.rule.Severity; +import org.sonar.api.server.debt.DebtRemediationFunction; +import org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction; +import org.sonar.api.utils.System2; +import org.sonar.db.DbSession; +import org.sonar.db.DbTester; +import org.sonar.db.qualityprofile.ActiveRuleDto; +import org.sonar.db.qualityprofile.ActiveRuleKey; +import org.sonar.db.qualityprofile.ActiveRuleParamDto; +import org.sonar.db.qualityprofile.QualityProfileDto; +import org.sonar.db.rule.RuleDefinitionDto; +import org.sonar.db.rule.RuleDto; +import org.sonar.db.rule.RuleParamDto; +import org.sonar.db.rule.RuleTesting; +import org.sonar.server.es.EsTester; +import org.sonar.server.es.SearchOptions; +import org.sonar.server.organization.TestDefaultOrganizationProvider; +import org.sonar.server.qualityprofile.QProfileTesting; +import org.sonar.server.rule.index.RuleIndex; +import org.sonar.server.rule.index.RuleIndexDefinition; +import org.sonar.server.rule.index.RuleIndexer; +import org.sonar.server.rule.index.RuleQuery; +import org.sonar.server.tester.UserSessionRule; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; + +public class RuleUpdaterTest { + + static final RuleKey RULE_KEY = RuleKey.of("squid", "S001"); + + private System2 system2 = mock(System2.class); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Rule + public UserSessionRule userSessionRule = UserSessionRule.standalone(); + + @Rule + public DbTester db = DbTester.create(system2); + + @Rule + public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings())); + + private RuleIndex ruleIndex = new RuleIndex(es.client()); + private RuleIndexer ruleIndexer = new RuleIndexer(es.client(), db.getDbClient()); + private DbSession dbSession = db.getSession(); + private TestDefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db); + + private RuleUpdater underTest = new RuleUpdater(db.getDbClient(), ruleIndexer, system2); + + @Test + public void do_not_update_rule_with_removed_status() { + db.rules().insert(RuleTesting.newRule(RULE_KEY).setStatus(RuleStatus.REMOVED)); + dbSession.commit(); + + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) + .setTags(Sets.newHashSet("java9")) + .setOrganization(db.getDefaultOrganization()); + try { + underTest.update(dbSession, update, db.getDefaultOrganization(), userSessionRule); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage("Rule with REMOVED status cannot be updated: squid:S001"); + } + } + + @Test + public void no_changes() { + RuleDto ruleDto = RuleTesting.newDto(RULE_KEY, db.getDefaultOrganization()) + // the following fields are not supposed to be updated + .setNoteData("my *note*") + .setNoteUserLogin("me") + .setTags(ImmutableSet.of("tag1")) + .setRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()) + .setRemediationGapMultiplier("1d") + .setRemediationBaseEffort("5min"); + db.rules().insert(ruleDto.getDefinition()); + db.rules().insertOrUpdateMetadata(ruleDto.getMetadata().setRuleId(ruleDto.getId())); + dbSession.commit(); + + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY); + assertThat(update.isEmpty()).isTrue(); + underTest.update(dbSession, update, db.getDefaultOrganization(), userSessionRule); + + dbSession.clearCache(); + RuleDto rule = db.getDbClient().ruleDao().selectOrFailByKey(dbSession, db.getDefaultOrganization(), RULE_KEY); + assertThat(rule.getNoteData()).isEqualTo("my *note*"); + assertThat(rule.getNoteUserLogin()).isEqualTo("me"); + assertThat(rule.getTags()).containsOnly("tag1"); + assertThat(rule.getRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()); + assertThat(rule.getRemediationGapMultiplier()).isEqualTo("1d"); + assertThat(rule.getRemediationBaseEffort()).isEqualTo("5min"); + } + + @Test + public void set_markdown_note() { + userSessionRule.logIn("me"); + + RuleDto ruleDto = RuleTesting.newDto(RULE_KEY, db.getDefaultOrganization()) + .setNoteData(null) + .setNoteUserLogin(null) + + // the following fields are not supposed to be updated + .setTags(ImmutableSet.of("tag1")) + .setRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()) + .setRemediationGapMultiplier("1d") + .setRemediationBaseEffort("5min"); + db.rules().insert(ruleDto.getDefinition()); + db.rules().insertOrUpdateMetadata(ruleDto.getMetadata().setRuleId(ruleDto.getId())); + dbSession.commit(); + + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) + .setMarkdownNote("my *note*") + .setOrganization(db.getDefaultOrganization()); + underTest.update(dbSession, update, db.getDefaultOrganization(), userSessionRule); + + dbSession.clearCache(); + RuleDto rule = db.getDbClient().ruleDao().selectOrFailByKey(dbSession, db.getDefaultOrganization(), RULE_KEY); + assertThat(rule.getNoteData()).isEqualTo("my *note*"); + assertThat(rule.getNoteUserLogin()).isEqualTo("me"); + assertThat(rule.getNoteCreatedAt()).isNotNull(); + assertThat(rule.getNoteUpdatedAt()).isNotNull(); + // no other changes + assertThat(rule.getTags()).containsOnly("tag1"); + assertThat(rule.getRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()); + assertThat(rule.getRemediationGapMultiplier()).isEqualTo("1d"); + assertThat(rule.getRemediationBaseEffort()).isEqualTo("5min"); + } + + @Test + public void remove_markdown_note() { + RuleDto ruleDto = RuleTesting.newDto(RULE_KEY, db.getDefaultOrganization()) + .setNoteData("my *note*") + .setNoteUserLogin("me"); + db.rules().insert(ruleDto.getDefinition()); + db.rules().insertOrUpdateMetadata(ruleDto.getMetadata().setRuleId(ruleDto.getId())); + dbSession.commit(); + + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) + .setMarkdownNote(null) + .setOrganization(db.getDefaultOrganization()); + underTest.update(dbSession, update, db.getDefaultOrganization(), userSessionRule); + + dbSession.clearCache(); + RuleDto rule = db.getDbClient().ruleDao().selectOrFailByKey(dbSession, db.getDefaultOrganization(), RULE_KEY); + assertThat(rule.getNoteData()).isNull(); + assertThat(rule.getNoteUserLogin()).isNull(); + assertThat(rule.getNoteCreatedAt()).isNull(); + assertThat(rule.getNoteUpdatedAt()).isNull(); + } + + @Test + public void set_tags() { + // insert db + db.rules().insert(RuleTesting.newDto(RULE_KEY, db.getDefaultOrganization()) + .setTags(Sets.newHashSet("security")) + .setSystemTags(Sets.newHashSet("java8", "javadoc")).getDefinition()); + dbSession.commit(); + + // java8 is a system tag -> ignore + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) + .setTags(Sets.newHashSet("bug", "java8")) + .setOrganization(db.getDefaultOrganization()); + underTest.update(dbSession, update, db.getDefaultOrganization(), userSessionRule); + + RuleDto rule = db.getDbClient().ruleDao().selectOrFailByKey(dbSession, db.getDefaultOrganization(), RULE_KEY); + assertThat(rule.getTags()).containsOnly("bug"); + assertThat(rule.getSystemTags()).containsOnly("java8", "javadoc"); + + // verify that tags are indexed in index + List tags = ruleIndex.listTags(db.getDefaultOrganization(), null, 10); + assertThat(tags).containsExactly("bug", "java8", "javadoc"); + } + + @Test + public void remove_tags() { + RuleDto ruleDto = RuleTesting.newDto(RULE_KEY, db.getDefaultOrganization()) + .setTags(Sets.newHashSet("security")) + .setSystemTags(Sets.newHashSet("java8", "javadoc")); + db.rules().insert(ruleDto.getDefinition()); + db.rules().insertOrUpdateMetadata(ruleDto.getMetadata()); + dbSession.commit(); + + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) + .setTags(null) + .setOrganization(db.getDefaultOrganization()); + underTest.update(dbSession, update, db.getDefaultOrganization(), userSessionRule); + + dbSession.clearCache(); + RuleDto rule = db.getDbClient().ruleDao().selectOrFailByKey(dbSession, db.getDefaultOrganization(), RULE_KEY); + assertThat(rule.getTags()).isEmpty(); + assertThat(rule.getSystemTags()).containsOnly("java8", "javadoc"); + + // verify that tags are indexed in index + List tags = ruleIndex.listTags(db.getDefaultOrganization(), null, 10); + assertThat(tags).containsExactly("java8", "javadoc"); + } + + @Test + public void override_debt() { + db.rules().insert(RuleTesting.newRule(RULE_KEY) + .setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setDefRemediationGapMultiplier("1d") + .setDefRemediationBaseEffort("5min")); + dbSession.commit(); + + DefaultDebtRemediationFunction fn = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, null, "1min"); + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) + .setDebtRemediationFunction(fn) + .setOrganization(db.getDefaultOrganization()); + underTest.update(dbSession, update, db.getDefaultOrganization(), userSessionRule); + dbSession.clearCache(); + + // verify debt is overridden + RuleDto rule = db.getDbClient().ruleDao().selectOrFailByKey(dbSession, db.getDefaultOrganization(), RULE_KEY); + assertThat(rule.getRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()); + assertThat(rule.getRemediationGapMultiplier()).isNull(); + assertThat(rule.getRemediationBaseEffort()).isEqualTo("1min"); + + assertThat(rule.getDefRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET.name()); + assertThat(rule.getDefRemediationGapMultiplier()).isEqualTo("1d"); + assertThat(rule.getDefRemediationBaseEffort()).isEqualTo("5min"); + } + + @Test + public void override_debt_only_offset() { + db.rules().insert(RuleTesting.newRule(RULE_KEY) + .setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR.name()) + .setDefRemediationGapMultiplier("1d") + .setDefRemediationBaseEffort(null)); + dbSession.commit(); + + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) + .setDebtRemediationFunction(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, "2d", null)) + .setOrganization(db.getDefaultOrganization()); + underTest.update(dbSession, update, db.getDefaultOrganization(), userSessionRule); + dbSession.clearCache(); + + // verify debt is overridden + RuleDto rule = db.getDbClient().ruleDao().selectOrFailByKey(dbSession, db.getDefaultOrganization(), RULE_KEY); + assertThat(rule.getRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.LINEAR.name()); + assertThat(rule.getRemediationGapMultiplier()).isEqualTo("2d"); + assertThat(rule.getRemediationBaseEffort()).isNull(); + + assertThat(rule.getDefRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.LINEAR.name()); + assertThat(rule.getDefRemediationGapMultiplier()).isEqualTo("1d"); + assertThat(rule.getDefRemediationBaseEffort()).isNull(); + } + + @Test + public void override_debt_from_linear_with_offset_to_constant() { + db.rules().insert(RuleTesting.newRule(RULE_KEY) + .setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setDefRemediationGapMultiplier("1d") + .setDefRemediationBaseEffort("5min")); + dbSession.commit(); + + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) + .setDebtRemediationFunction(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, null, "10min")) + .setOrganization(db.getDefaultOrganization()); + underTest.update(dbSession, update, db.getDefaultOrganization(), userSessionRule); + dbSession.clearCache(); + + // verify debt is overridden + RuleDto rule = db.getDbClient().ruleDao().selectOrFailByKey(dbSession, db.getDefaultOrganization(), RULE_KEY); + assertThat(rule.getRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()); + assertThat(rule.getRemediationGapMultiplier()).isNull(); + assertThat(rule.getRemediationBaseEffort()).isEqualTo("10min"); + + assertThat(rule.getDefRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET.name()); + assertThat(rule.getDefRemediationGapMultiplier()).isEqualTo("1d"); + assertThat(rule.getDefRemediationBaseEffort()).isEqualTo("5min"); + } + + @Test + public void reset_remediation_function() { + RuleDto ruleDto = RuleTesting.newDto(RULE_KEY, db.getDefaultOrganization()) + .setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR.name()) + .setDefRemediationGapMultiplier("1d") + .setDefRemediationBaseEffort("5min") + .setRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()) + .setRemediationGapMultiplier(null) + .setRemediationBaseEffort("1min"); + db.rules().insert(ruleDto.getDefinition()); + db.rules().insertOrUpdateMetadata(ruleDto.getMetadata().setRuleId(ruleDto.getId())); + dbSession.commit(); + + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) + .setDebtRemediationFunction(null) + .setOrganization(db.getDefaultOrganization()); + underTest.update(dbSession, update, db.getDefaultOrganization(), userSessionRule); + dbSession.clearCache(); + + // verify debt is coming from default values + RuleDto rule = db.getDbClient().ruleDao().selectOrFailByKey(dbSession, db.getDefaultOrganization(), RULE_KEY); + assertThat(rule.getDefRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.LINEAR.name()); + assertThat(rule.getDefRemediationGapMultiplier()).isEqualTo("1d"); + assertThat(rule.getDefRemediationBaseEffort()).isEqualTo("5min"); + + assertThat(rule.getRemediationFunction()).isNull(); + assertThat(rule.getRemediationGapMultiplier()).isNull(); + assertThat(rule.getRemediationBaseEffort()).isNull(); + } + + @Test + public void update_custom_rule() { + // Create template rule + RuleDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001")); + db.rules().insert(templateRule.getDefinition()); + db.rules().insertRuleParam(templateRule.getDefinition(), param -> param.setName("regex").setType("STRING").setDescription("Reg ex").setDefaultValue(".*")); + db.rules().insertRuleParam(templateRule.getDefinition(), param -> param.setName("format").setType("STRING").setDescription("Format")); + + // Create custom rule + RuleDefinitionDto customRule = RuleTesting.newCustomRule(templateRule) + .setName("Old name") + .setDescription("Old description") + .setSeverity(Severity.MINOR) + .setStatus(RuleStatus.BETA) + .getDefinition(); + db.rules().insert(customRule); + db.rules().insertRuleParam(customRule, param -> param.setName("regex").setType("STRING").setDescription("Reg ex").setDefaultValue("a.*")); + db.rules().insertRuleParam(customRule, param -> param.setName("format").setType("STRING").setDescription("Format").setDefaultValue(null)); + + // Update custom rule + RuleUpdate update = RuleUpdate.createForCustomRule(customRule.getKey()) + .setName("New name") + .setMarkdownDescription("New description") + .setSeverity("MAJOR") + .setStatus(RuleStatus.READY) + .setParameters(ImmutableMap.of("regex", "b.*")) + .setOrganization(db.getDefaultOrganization()); + underTest.update(dbSession, update, db.getDefaultOrganization(), userSessionRule); + + dbSession.clearCache(); + + // Verify custom rule is updated + RuleDto customRuleReloaded = db.getDbClient().ruleDao().selectOrFailByKey(dbSession, db.getDefaultOrganization(), customRule.getKey()); + assertThat(customRuleReloaded).isNotNull(); + assertThat(customRuleReloaded.getName()).isEqualTo("New name"); + assertThat(customRuleReloaded.getDescription()).isEqualTo("New description"); + assertThat(customRuleReloaded.getSeverityString()).isEqualTo("MAJOR"); + assertThat(customRuleReloaded.getStatus()).isEqualTo(RuleStatus.READY); + + List params = db.getDbClient().ruleDao().selectRuleParamsByRuleKey(dbSession, customRuleReloaded.getKey()); + assertThat(params).extracting(RuleParamDto::getDefaultValue).containsOnly("b.*", null); + + // Verify in index + assertThat(ruleIndex.search(new RuleQuery().setQueryText("New name"), new SearchOptions()).getIds()).containsOnly(customRule.getKey()); + assertThat(ruleIndex.search(new RuleQuery().setQueryText("New description"), new SearchOptions()).getIds()).containsOnly(customRule.getKey()); + + assertThat(ruleIndex.search(new RuleQuery().setQueryText("Old name"), new SearchOptions()).getTotal()).isZero(); + assertThat(ruleIndex.search(new RuleQuery().setQueryText("Old description"), new SearchOptions()).getTotal()).isZero(); + } + + @Test + public void update_custom_rule_with_empty_parameter() { + // Create template rule + RuleDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001")); + db.rules().insert(templateRule.getDefinition()); + db.rules().insertRuleParam(templateRule.getDefinition(), param -> param.setName("regex").setType("STRING").setDescription("Reg ex").setDefaultValue(null)); + + // Create custom rule + RuleDefinitionDto customRule = RuleTesting.newCustomRule(templateRule) + .setName("Old name") + .setDescription("Old description") + .setSeverity(Severity.MINOR) + .setStatus(RuleStatus.BETA) + .getDefinition(); + db.rules().insert(customRule); + db.rules().insertRuleParam(customRule, param -> param.setName("regex").setType("STRING").setDescription("Reg ex").setDefaultValue(null)); + + dbSession.commit(); + + // Update custom rule without setting a value for the parameter + RuleUpdate update = RuleUpdate.createForCustomRule(customRule.getKey()) + .setName("New name") + .setMarkdownDescription("New description") + .setSeverity("MAJOR") + .setStatus(RuleStatus.READY) + .setOrganization(db.getDefaultOrganization()); + underTest.update(dbSession, update, db.getDefaultOrganization(), userSessionRule); + + dbSession.clearCache(); + + // Verify custom rule is updated + List params = db.getDbClient().ruleDao().selectRuleParamsByRuleKey(dbSession, customRule.getKey()); + assertThat(params.get(0).getDefaultValue()).isNull(); + } + + @Test + public void update_active_rule_parameters_when_updating_custom_rule() { + // Create template rule with 3 parameters + RuleDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001")).setLanguage("xoo"); + RuleDefinitionDto templateRuleDefinition = templateRule.getDefinition(); + db.rules().insert(templateRuleDefinition); + db.rules().insertRuleParam(templateRuleDefinition, param -> param.setName("regex").setType("STRING").setDescription("Reg ex").setDefaultValue(".*")); + db.rules().insertRuleParam(templateRuleDefinition, param -> param.setName("format").setType("STRING").setDescription("format").setDefaultValue("csv")); + db.rules().insertRuleParam(templateRuleDefinition, param -> param.setName("message").setType("STRING").setDescription("message")); + + // Create custom rule + RuleDefinitionDto customRule = RuleTesting.newCustomRule(templateRule) + .setSeverity(Severity.MAJOR) + .setLanguage("xoo") + .getDefinition(); + db.rules().insert(customRule); + RuleParamDto ruleParam1 = db.rules().insertRuleParam(customRule, param -> param.setName("regex").setType("STRING").setDescription("Reg ex").setDefaultValue("a.*")); + db.rules().insertRuleParam(customRule, param -> param.setName("format").setType("STRING").setDescription("format").setDefaultValue("txt")); + db.rules().insertRuleParam(customRule, param -> param.setName("message").setType("STRING").setDescription("message")); + + // Create a quality profile + QualityProfileDto profileDto = QProfileTesting.newXooP1(db.getDefaultOrganization()); + db.getDbClient().qualityProfileDao().insert(dbSession, profileDto); + dbSession.commit(); + + // Activate the custom rule + ActiveRuleDto activeRuleDto = new ActiveRuleDto() + .setProfileId(profileDto.getId()) + .setRuleId(customRule.getId()) + .setSeverity(Severity.BLOCKER); + db.getDbClient().activeRuleDao().insert(dbSession, activeRuleDto); + db.getDbClient().activeRuleDao().insertParam(dbSession, activeRuleDto, new ActiveRuleParamDto() + .setActiveRuleId(activeRuleDto.getId()) + .setRulesParameterId(ruleParam1.getId()) + .setKey(ruleParam1.getName()) + .setValue(ruleParam1.getDefaultValue())); + dbSession.commit(); + + // Update custom rule parameter 'regex', add 'message' and remove 'format' + RuleUpdate update = RuleUpdate.createForCustomRule(customRule.getKey()) + .setParameters(ImmutableMap.of("regex", "b.*", "message", "a message")) + .setOrganization(db.getDefaultOrganization()); + underTest.update(dbSession, update, db.getDefaultOrganization(), userSessionRule); + + // Verify custom rule parameters has been updated + List params = db.getDbClient().ruleDao().selectRuleParamsByRuleKey(dbSession, customRule.getKey()); + assertThat(params).hasSize(3); + + Map paramsByKey = paramsByKey(params); + assertThat(paramsByKey.get("regex")).isNotNull(); + assertThat(paramsByKey.get("regex").getDefaultValue()).isEqualTo("b.*"); + assertThat(paramsByKey.get("message")).isNotNull(); + assertThat(paramsByKey.get("message").getDefaultValue()).isEqualTo("a message"); + assertThat(paramsByKey.get("format")).isNotNull(); + assertThat(paramsByKey.get("format").getDefaultValue()).isNull(); + + // Verify that severity has not changed + ActiveRuleDto activeRuleReloaded = db.getDbClient().activeRuleDao().selectOrFailByKey(dbSession, ActiveRuleKey.of(profileDto.getKey(), customRule.getKey())); + assertThat(activeRuleReloaded.getSeverityString()).isEqualTo(Severity.BLOCKER); + + // Verify active rule parameters has been updated + List activeRuleParams = db.getDbClient().activeRuleDao().selectParamsByActiveRuleId(dbSession, activeRuleReloaded.getId()); + + assertThat(activeRuleParams).hasSize(2); + Map activeRuleParamsByKey = ActiveRuleParamDto.groupByKey(activeRuleParams); + assertThat(activeRuleParamsByKey.get("regex").getValue()).isEqualTo("b.*"); + assertThat(activeRuleParamsByKey.get("message").getValue()).isEqualTo("a message"); + assertThat(activeRuleParamsByKey.get("format")).isNull(); + } + + @Test + public void fail_to_update_custom_rule_when_empty_name() { + // Create template rule + RuleDefinitionDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001")).getDefinition(); + db.rules().insert(templateRule); + + // Create custom rule + RuleDefinitionDto customRule = RuleTesting.newCustomRule(templateRule); + db.rules().insert(customRule); + + dbSession.commit(); + + // Update custom rule + RuleUpdate update = RuleUpdate.createForCustomRule(customRule.getKey()) + .setName("") + .setMarkdownDescription("New desc") + .setOrganization(db.getDefaultOrganization()); + try { + underTest.update(dbSession, update, db.getDefaultOrganization(), userSessionRule); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("The name is missing"); + } + } + + @Test + public void fail_to_update_custom_rule_when_empty_description() { + // Create template rule + RuleDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001")); + db.rules().insert(templateRule.getDefinition()); + + // Create custom rule + RuleDto customRule = RuleTesting.newCustomRule(templateRule); + db.rules().insert(customRule.getDefinition()); + + dbSession.commit(); + + // Update custom rule + RuleUpdate update = RuleUpdate.createForCustomRule(customRule.getKey()) + .setName("New name") + .setMarkdownDescription("") + .setOrganization(db.getDefaultOrganization()); + try { + underTest.update(dbSession, update, db.getDefaultOrganization(), userSessionRule); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("The description is missing"); + } + } + + @Test + public void fail_to_update_plugin_rule_if_name_is_set() { + // Create rule rule + RuleDefinitionDto ruleDto = RuleTesting.newRule(RuleKey.of("squid", "S01")); + db.rules().insert(ruleDto); + + dbSession.commit(); + + try { + // Update rule + RuleUpdate.createForPluginRule(ruleDto.getKey()) + .setName("New name"); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not a custom rule"); + } + } + + @Test + public void fail_to_update_plugin_rule_if_description_is_set() { + // Create rule rule + RuleDefinitionDto ruleDto = RuleTesting.newRule(RuleKey.of("squid", "S01")); + db.rules().insert(ruleDto); + + dbSession.commit(); + + try { + // Update rule + RuleUpdate.createForPluginRule(ruleDto.getKey()) + .setMarkdownDescription("New description"); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not a custom rule"); + } + } + + @Test + public void fail_to_update_plugin_rule_if_severity_is_set() { + // Create rule rule + RuleDefinitionDto ruleDto = RuleTesting.newRule(RuleKey.of("squid", "S01")); + db.rules().insert(ruleDto); + + dbSession.commit(); + + try { + // Update rule + RuleUpdate.createForPluginRule(ruleDto.getKey()) + .setSeverity(Severity.CRITICAL); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not a custom rule"); + } + } + + private static Map paramsByKey(List params) { + return FluentIterable.from(params).uniqueIndex(RuleParamToKey.INSTANCE); + } + + private enum RuleParamToKey implements Function { + INSTANCE; + + @Override + public String apply(@Nonnull RuleParamDto input) { + return input.getName(); + } + } +}