From 3665c9298b15f8d5242259df84482574fdf62b5e Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Mon, 16 Jun 2014 14:08:01 +0200 Subject: [PATCH] SONAR-4514 New web service to manage manual rules --- .../java/org/sonar/server/rule/NewRule.java | 47 ++-- .../sonar/server/rule/RubyRuleService.java | 2 +- .../main/java/org/sonar/server/rule/Rule.java | 2 + .../org/sonar/server/rule/RuleCreator.java | 68 ++++-- .../org/sonar/server/rule/RuleUpdate.java | 40 +++- .../org/sonar/server/rule/index/RuleDoc.java | 23 +- .../sonar/server/rule/ws/CreateAction.java | 60 +++-- .../sonar/server/rule/ws/UpdateAction.java | 4 +- .../server/rule/RegisterRulesMediumTest.java | 12 +- .../server/rule/RuleCreatorMediumTest.java | 211 ++++++++++++++---- .../server/rule/RuleServiceMediumTest.java | 18 +- .../org/sonar/server/rule/RuleTesting.java | 7 + .../server/rule/RuleUpdaterMediumTest.java | 137 +++++++++++- .../rule/ws/CreateActionMediumTest.java | 53 ++++- .../rule/ws/UpdateActionMediumTest.java | 4 +- .../create_manual_rule.json | 14 ++ .../create_manual_rule_without_severity.json | 13 ++ 17 files changed, 579 insertions(+), 136 deletions(-) create mode 100644 sonar-server/src/test/resources/org/sonar/server/rule/ws/CreateActionMediumTest/create_manual_rule.json create mode 100644 sonar-server/src/test/resources/org/sonar/server/rule/ws/CreateActionMediumTest/create_manual_rule_without_severity.json diff --git a/sonar-server/src/main/java/org/sonar/server/rule/NewRule.java b/sonar-server/src/main/java/org/sonar/server/rule/NewRule.java index 4ae05bf8632..3b2b2539a0a 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/NewRule.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/NewRule.java @@ -19,6 +19,8 @@ */ package org.sonar.server.rule; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; import com.google.common.collect.Maps; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.RuleStatus; @@ -36,13 +38,14 @@ public class NewRule { private RuleStatus status; private final Map parameters = Maps.newHashMap(); - public String ruleKey() { - return ruleKey; + private boolean isCustomRule = false; + + private NewRule() { + // No direct call to constructor } - public NewRule setRuleKey(String ruleKey) { - this.ruleKey = ruleKey; - return this; + public String ruleKey() { + return ruleKey; } @CheckForNull @@ -50,14 +53,6 @@ public class NewRule { return templateKey; } - /** - * For the creation a custom rule - */ - public NewRule setTemplateKey(@Nullable RuleKey templateKey) { - this.templateKey = templateKey; - return this; - } - @CheckForNull public String name() { return name; @@ -94,6 +89,7 @@ public class NewRule { } public NewRule setStatus(@Nullable RuleStatus status) { + checkCustomRule(); this.status = status; return this; } @@ -108,8 +104,33 @@ public class NewRule { } public NewRule setParameters(Map params) { + checkCustomRule(); this.parameters.clear(); this.parameters.putAll(params); return this; } + + private void checkCustomRule(){ + if (!isCustomRule) { + throw new IllegalStateException("Not a custom rule"); + } + } + + public static NewRule createForCustomRule(String customKey, RuleKey templateKey) { + Preconditions.checkArgument(!Strings.isNullOrEmpty(customKey), "Custom key should be set"); + Preconditions.checkArgument(templateKey != null, "Template key should be set"); + NewRule newRule = new NewRule(); + newRule.ruleKey = customKey; + newRule.templateKey = templateKey; + newRule.isCustomRule = true; + return newRule; + } + + public static NewRule createForManualRule(String manualKey) { + Preconditions.checkArgument(!Strings.isNullOrEmpty(manualKey), "Manual key should be set"); + NewRule newRule = new NewRule(); + newRule.ruleKey = manualKey; + return newRule; + } + } diff --git a/sonar-server/src/main/java/org/sonar/server/rule/RubyRuleService.java b/sonar-server/src/main/java/org/sonar/server/rule/RubyRuleService.java index 66a27e4ab80..ef362e4372d 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/RubyRuleService.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/RubyRuleService.java @@ -87,7 +87,7 @@ public class RubyRuleService implements ServerComponent, Startable { // sqale public void updateRule(Map params) { - RuleUpdate update = new RuleUpdate(RuleKey.parse((String) params.get("ruleKey"))); + RuleUpdate update = RuleUpdate.createForPluginRule(RuleKey.parse((String) params.get("ruleKey"))); update.setDebtSubCharacteristic(Strings.emptyToNull((String) params.get("debtCharacteristicKey"))); String fn = (String) params.get("debtRemediationFunction"); if (fn == null) { diff --git a/sonar-server/src/main/java/org/sonar/server/rule/Rule.java b/sonar-server/src/main/java/org/sonar/server/rule/Rule.java index 5237f23c7b1..74b785903ad 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/Rule.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/Rule.java @@ -100,4 +100,6 @@ public interface Rule { @CheckForNull Date noteUpdatedAt(); + + boolean isManual(); } diff --git a/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java b/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java index 6e43422287e..48ad462dce3 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java @@ -23,11 +23,13 @@ package org.sonar.server.rule; import com.google.common.base.Strings; import org.sonar.api.ServerComponent; import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; import org.sonar.api.rule.Severity; import org.sonar.core.persistence.DbSession; import org.sonar.core.rule.RuleDto; import org.sonar.core.rule.RuleParamDto; import org.sonar.server.db.DbClient; +import org.sonar.server.rule.index.RuleDoc; public class RuleCreator implements ServerComponent { @@ -41,33 +43,41 @@ public class RuleCreator implements ServerComponent { DbSession dbSession = dbClient.openSession(false); try { RuleKey templateKey = newRule.templateKey(); + // Creation of a custom rule if (templateKey != null) { RuleDto templateRule = dbClient.ruleDao().getByKey(dbSession, templateKey); if (!templateRule.isTemplate()) { throw new IllegalArgumentException("This rule is not a template rule: " + templateKey.toString()); } - validateRule(newRule); + validateCustomRule(newRule); RuleKey customRuleKey = RuleKey.of(templateRule.getRepositoryKey(), newRule.ruleKey()); checkRuleKeyUnicity(customRuleKey, dbSession); createCustomRule(customRuleKey, newRule, templateRule, dbSession); + + dbSession.commit(); + return customRuleKey; + } else { + // Creation of a manual rule + validateManualRule(newRule); + + RuleKey customRuleKey = RuleKey.of(RuleDoc.MANUAL_REPOSITORY, newRule.ruleKey()); + checkRuleKeyUnicity(customRuleKey, dbSession); + createManualRule(customRuleKey, newRule, dbSession); + dbSession.commit(); return customRuleKey; } - throw new IllegalArgumentException("Not supported"); } finally { dbSession.close(); } } - private static void validateRule(NewRule newRule) { + private static void validateCustomRule(NewRule newRule) { validateRuleKey(newRule.ruleKey()); - if (Strings.isNullOrEmpty(newRule.name())) { - throw new IllegalArgumentException("The name is missing"); - } - if (Strings.isNullOrEmpty(newRule.htmlDescription())) { - throw new IllegalArgumentException("The description is missing"); - } + validateName(newRule); + validateDescription(newRule); + String severity = newRule.severity(); if (Strings.isNullOrEmpty(severity)) { throw new IllegalArgumentException("The severity is missing"); @@ -79,13 +89,31 @@ public class RuleCreator implements ServerComponent { } } + private static void validateManualRule(NewRule newRule) { + validateRuleKey(newRule.ruleKey()); + validateName(newRule); + validateDescription(newRule); + + if (!newRule.parameters().isEmpty()) { + throw new IllegalArgumentException("No parameter can be set on a manual rule"); + } + } + + private static void validateName(NewRule newRule){ + if (Strings.isNullOrEmpty(newRule.name())) { + throw new IllegalArgumentException("The name is missing"); + } + } + + private static void validateDescription(NewRule newRule){ + if (Strings.isNullOrEmpty(newRule.htmlDescription())) { + throw new IllegalArgumentException("The description is missing"); + } + } + private static void validateRuleKey(String ruleKey) { - if (Strings.isNullOrEmpty(ruleKey)) { - throw new IllegalArgumentException("The rule key is missing"); - } else { - if (!ruleKey.matches("^[\\w]+$")) { - throw new IllegalArgumentException(String.format("The rule key '%s' is invalid, it should only contains : a-z, 0-9, '_'", ruleKey)); - } + if (!ruleKey.matches("^[\\w]+$")) { + throw new IllegalArgumentException(String.format("The rule key '%s' is invalid, it should only contains : a-z, 0-9, '_'", ruleKey)); } } @@ -131,4 +159,14 @@ public class RuleCreator implements ServerComponent { dbClient.ruleDao().addRuleParam(dbSession, ruleDto, ruleParamDto); } + private RuleKey createManualRule(RuleKey ruleKey, NewRule newRule, DbSession dbSession){ + RuleDto ruleDto = RuleDto.createFor(ruleKey) + .setName(newRule.name()) + .setDescription(newRule.htmlDescription()) + .setSeverity(newRule.severity()) + .setStatus(RuleStatus.READY); + dbClient.ruleDao().insert(dbSession, ruleDto); + return ruleKey; + } + } diff --git a/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdate.java b/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdate.java index 584053fa04f..3b2f080afdd 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdate.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdate.java @@ -39,7 +39,7 @@ public class RuleUpdate { private boolean changeTags = false, changeMarkdownNote = false, changeDebtSubCharacteristic = false, changeDebtRemediationFunction = false, changeName = false, changeDescription = false, changeSeverity = false, changeStatus = false, changeParameters = false; - private boolean isCustomRule = false; + private boolean isCustomRule, isManual; private Set tags; private String markdownNote; private String debtSubCharacteristicKey; @@ -49,7 +49,7 @@ public class RuleUpdate { private RuleStatus status; private final Map parameters = Maps.newHashMap(); - public RuleUpdate(RuleKey ruleKey) { + private RuleUpdate(RuleKey ruleKey) { this.ruleKey = ruleKey; } @@ -117,7 +117,7 @@ public class RuleUpdate { } public RuleUpdate setName(@Nullable String name) { - checkCustomRule(); + checkCustomOrManualRule(); this.name = name; this.changeName = true; return this; @@ -129,7 +129,7 @@ public class RuleUpdate { } public RuleUpdate setHtmlDescription(@Nullable String htmlDescription) { - checkCustomRule(); + checkCustomOrManualRule(); this.htmlDescription = htmlDescription; this.changeDescription = true; return this; @@ -141,7 +141,7 @@ public class RuleUpdate { } public RuleUpdate setSeverity(@Nullable String severity) { - checkCustomRule(); + checkCustomOrManualRule(); this.severity = severity; this.changeSeverity = true; return this; @@ -233,13 +233,39 @@ public class RuleUpdate { } } - public static RuleUpdate createForRule(RuleKey ruleKey) { - return new RuleUpdate(ruleKey); + private void checkCustomOrManualRule(){ + if (!isCustomRule && !isManual) { + throw new IllegalStateException("Not a custom or a manual rule"); + } + } + + /** + * Use to update a rule provided by a plugin (name, description, severity, status and parameters cannot by changed) + */ + public static RuleUpdate createForPluginRule(RuleKey ruleKey) { + RuleUpdate ruleUpdate = new RuleUpdate(ruleKey); + ruleUpdate.isCustomRule = false; + ruleUpdate.isManual = false; + return ruleUpdate; } + /** + * Use to update a custom rule + */ public static RuleUpdate createForCustomRule(RuleKey ruleKey) { RuleUpdate ruleUpdate = new RuleUpdate(ruleKey); ruleUpdate.isCustomRule = true; + ruleUpdate.isManual = false; + return ruleUpdate; + } + + /** + * Use to update a manual rule (status and parameters cannot by changed) + */ + public static RuleUpdate createForManualRule(RuleKey ruleKey) { + RuleUpdate ruleUpdate = new RuleUpdate(ruleKey); + ruleUpdate.isManual = true; + ruleUpdate.isCustomRule = false; return ruleUpdate; } diff --git a/sonar-server/src/main/java/org/sonar/server/rule/index/RuleDoc.java b/sonar-server/src/main/java/org/sonar/server/rule/index/RuleDoc.java index 960baebd6a5..3d3d7b30186 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/index/RuleDoc.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/index/RuleDoc.java @@ -44,6 +44,8 @@ import java.util.Map; */ public class RuleDoc extends BaseDoc implements Rule { + public final static String MANUAL_REPOSITORY = "manual"; + RuleDoc(@Nullable Map fields) { super(fields); } @@ -69,13 +71,15 @@ public class RuleDoc extends BaseDoc implements Rule { } @Override + @CheckForNull public String internalKey() { return getNullableField(RuleNormalizer.RuleField.INTERNAL_KEY.field()); } @Override + @CheckForNull public String language() { - return getField(RuleNormalizer.RuleField.LANGUAGE.field()); + return getNullableField(RuleNormalizer.RuleField.LANGUAGE.field()); } @Override @@ -89,11 +93,13 @@ public class RuleDoc extends BaseDoc implements Rule { } @Override + @CheckForNull public String severity() { - return (String) getField(RuleNormalizer.RuleField.SEVERITY.field()); + return (String) getNullableField(RuleNormalizer.RuleField.SEVERITY.field()); } @Override + @CheckForNull public RuleStatus status() { return RuleStatus.valueOf((String) getField(RuleNormalizer.RuleField.STATUS.field())); } @@ -104,6 +110,7 @@ public class RuleDoc extends BaseDoc implements Rule { } @Override + @CheckForNull public RuleKey templateKey() { String templateKey = getNullableField(RuleNormalizer.RuleField.TEMPLATE_KEY.field()); return templateKey != null ? RuleKey.parse(templateKey) : null; @@ -170,16 +177,19 @@ public class RuleDoc extends BaseDoc implements Rule { } @Override + @CheckForNull public String debtCharacteristicKey() { return (String) getNullableField(RuleNormalizer.RuleField.CHARACTERISTIC.field()); } @Override + @CheckForNull public String debtSubCharacteristicKey() { return (String) getNullableField(RuleNormalizer.RuleField.SUB_CHARACTERISTIC.field()); } @Override + @CheckForNull public DebtRemediationFunction debtRemediationFunction() { final String function = getNullableField(RuleNormalizer.RuleField.DEBT_FUNCTION_TYPE.field()); if (function == null || function.isEmpty()) { @@ -205,21 +215,25 @@ public class RuleDoc extends BaseDoc implements Rule { } @Override + @CheckForNull public String markdownNote() { return getNullableField(RuleNormalizer.RuleField.NOTE.field()); } @Override + @CheckForNull public String noteLogin() { return (String) getNullableField(RuleNormalizer.RuleField.NOTE_LOGIN.field()); } @Override + @CheckForNull public Date noteCreatedAt() { return IndexUtils.parseDateTime((String) getNullableField(RuleNormalizer.RuleField.NOTE_CREATED_AT.field())); } @Override + @CheckForNull public Date noteUpdatedAt() { return IndexUtils.parseDateTime((String) getNullableField(RuleNormalizer.RuleField.NOTE_UPDATED_AT.field())); } @@ -234,6 +248,11 @@ public class RuleDoc extends BaseDoc implements Rule { return IndexUtils.parseDateTime((String) getNullableField(RuleNormalizer.RuleField.UPDATED_AT.field())); } + @Override + public boolean isManual() { + return getField(RuleNormalizer.RuleField.REPOSITORY.field()).equals(MANUAL_REPOSITORY); + } + @Override public String toString() { return ReflectionToStringBuilder.toString(this); diff --git a/sonar-server/src/main/java/org/sonar/server/rule/ws/CreateAction.java b/sonar-server/src/main/java/org/sonar/server/rule/ws/CreateAction.java index 0046a95e645..32a49c8aa6a 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/ws/CreateAction.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/ws/CreateAction.java @@ -29,6 +29,7 @@ import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.KeyValueFormat; import org.sonar.api.utils.text.JsonWriter; +import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.rule.NewRule; import org.sonar.server.rule.Rule; import org.sonar.server.rule.RuleService; @@ -39,7 +40,8 @@ import org.sonar.server.search.BaseDoc; */ public class CreateAction implements RequestHandler { - public static final String PARAM_KEY = "key"; + public static final String PARAM_CUSTOM_KEY = "custom_key"; + public static final String PARAM_MANUAL_KEY = "manual_key"; public static final String PARAM_NAME = "name"; public static final String PARAM_DESCRIPTION = "html_description"; public static final String PARAM_SEVERITY = "severity"; @@ -64,13 +66,18 @@ public class CreateAction implements RequestHandler { .setHandler(this); action - .createParam(PARAM_KEY) - .setDescription("Key of the rule") + .createParam(PARAM_CUSTOM_KEY) + .setDescription("Key of the custom rule") .setExampleValue("Todo_should_not_be_used"); + action + .createParam(PARAM_MANUAL_KEY) + .setDescription("Key of the manual rule") + .setExampleValue("Error_handling"); + action .createParam(PARAM_TEMPLATE_KEY) - .setDescription("Key of the template rule in order to create a custom rule") + .setDescription("Key of the template rule in order to create a custom rule (mandatory for custom rule)") .setExampleValue("java:XPath"); action @@ -87,36 +94,47 @@ public class CreateAction implements RequestHandler { action .createParam(PARAM_SEVERITY) - .setDescription("Rule severity") - .setRequired(true) + .setDescription("Rule severity (Only for custom rule)") .setPossibleValues(Severity.ALL); action .createParam(PARAM_STATUS) - .setDescription("Rule status") - .setRequired(true) + .setDescription("Rule status (Only for custom rule)") .setDefaultValue(RuleStatus.READY) .setPossibleValues(RuleStatus.values()); action.createParam(PARAMS) - .setDescription("Parameters as semi-colon list of =, for example 'params=key1=v1;key2=v2'"); + .setDescription("Parameters as semi-colon list of =, for example 'params=key1=v1;key2=v2' (Only for custom rule)"); } @Override public void handle(Request request, Response response) { - String templateRuleKey = request.param(PARAM_TEMPLATE_KEY); - NewRule newRule = new NewRule() - .setRuleKey(request.mandatoryParam(PARAM_KEY)) - .setTemplateKey(templateRuleKey != null ? RuleKey.parse(templateRuleKey) : null) - .setName(request.mandatoryParam(PARAM_NAME)) - .setHtmlDescription(request.mandatoryParam(PARAM_DESCRIPTION)) - .setSeverity(request.mandatoryParam(PARAM_SEVERITY)) - .setStatus(RuleStatus.valueOf(request.mandatoryParam(PARAM_STATUS))); - String params = request.param(PARAMS); - if (!Strings.isNullOrEmpty(params)) { - newRule.setParameters(KeyValueFormat.parse(params)); + String customKey = request.param(PARAM_CUSTOM_KEY); + String manualKey = request.param(PARAM_MANUAL_KEY); + if (Strings.isNullOrEmpty(customKey) && Strings.isNullOrEmpty(manualKey)) { + throw new BadRequestException(String.format("Either '%s' or '%s' parameters should be set", PARAM_CUSTOM_KEY, PARAM_MANUAL_KEY)); + } + + if (!Strings.isNullOrEmpty(customKey)) { + NewRule newRule = NewRule.createForCustomRule(customKey, RuleKey.parse(request.mandatoryParam(PARAM_TEMPLATE_KEY))) + .setName(request.mandatoryParam(PARAM_NAME)) + .setHtmlDescription(request.mandatoryParam(PARAM_DESCRIPTION)) + .setSeverity(request.mandatoryParam(PARAM_SEVERITY)) + .setStatus(RuleStatus.valueOf(request.mandatoryParam(PARAM_STATUS))); + String params = request.param(PARAMS); + if (!Strings.isNullOrEmpty(params)) { + newRule.setParameters(KeyValueFormat.parse(params)); + } + writeResponse(response, service.create(newRule)); + } + + if (!Strings.isNullOrEmpty(manualKey)) { + NewRule newRule = NewRule.createForManualRule(manualKey) + .setName(request.mandatoryParam(PARAM_NAME)) + .setHtmlDescription(request.mandatoryParam(PARAM_DESCRIPTION)) + .setSeverity(request.param(PARAM_SEVERITY)); + writeResponse(response, service.create(newRule)); } - writeResponse(response, service.create(newRule)); } private void writeResponse(Response response, RuleKey ruleKey) { diff --git a/sonar-server/src/main/java/org/sonar/server/rule/ws/UpdateAction.java b/sonar-server/src/main/java/org/sonar/server/rule/ws/UpdateAction.java index 656539f186f..0086b9d538b 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/ws/UpdateAction.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/ws/UpdateAction.java @@ -168,8 +168,10 @@ public class UpdateAction implements RequestHandler { } if (rule.templateKey() != null) { return RuleUpdate.createForCustomRule(key); + } else if (rule.isManual()) { + return RuleUpdate.createForManualRule(key); } else { - return RuleUpdate.createForRule(key); + return RuleUpdate.createForPluginRule(key); } } diff --git a/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesMediumTest.java index ea968ae0764..1c3b2bf51ad 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesMediumTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesMediumTest.java @@ -190,9 +190,7 @@ public class RegisterRulesMediumTest { Rule templateRule = index.getByKey(RuleKey.of("xoo", "template1")); // Create custom rule - RuleKey customRuleKey = tester.get(RuleCreator.class).create(new NewRule() - .setRuleKey("CUSTOM_RULE") - .setTemplateKey(templateRule.key()) + RuleKey customRuleKey = tester.get(RuleCreator.class).create(NewRule.createForCustomRule("CUSTOM_RULE", templateRule.key()) .setName("My custom") .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) @@ -230,9 +228,7 @@ public class RegisterRulesMediumTest { Rule templateRule = index.getByKey(RuleKey.of("xoo", "template1")); // Create custom rule - RuleKey customRuleKey = tester.get(RuleCreator.class).create(new NewRule() - .setRuleKey("CUSTOM_RULE") - .setTemplateKey(templateRule.key()) + RuleKey customRuleKey = tester.get(RuleCreator.class).create(NewRule.createForCustomRule("CUSTOM_RULE", templateRule.key()) .setName("My custom") .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) @@ -258,9 +254,7 @@ public class RegisterRulesMediumTest { Rule templateRule = index.getByKey(RuleKey.of("xoo", "template1")); // Create custom rule - RuleKey customRuleKey = tester.get(RuleCreator.class).create(new NewRule() - .setRuleKey("CUSTOM_RULE") - .setTemplateKey(templateRule.key()) + RuleKey customRuleKey = tester.get(RuleCreator.class).create(NewRule.createForCustomRule("CUSTOM_RULE", templateRule.key()) .setName("My custom") .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) diff --git a/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorMediumTest.java index fd6cb7435a5..9dfd4e6fbeb 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorMediumTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorMediumTest.java @@ -35,6 +35,7 @@ import org.sonar.core.rule.RuleDto; import org.sonar.core.rule.RuleParamDto; import org.sonar.server.db.DbClient; import org.sonar.server.rule.db.RuleDao; +import org.sonar.server.rule.index.RuleIndex; import org.sonar.server.tester.ServerTester; import java.util.List; @@ -51,6 +52,7 @@ public class RuleCreatorMediumTest { DbClient db = tester.get(DbClient.class); RuleDao dao = tester.get(RuleDao.class); RuleCreator creator = tester.get(RuleCreator.class); + RuleIndex ruleIndex = tester.get(RuleIndex.class); @Before public void before() { @@ -69,9 +71,7 @@ public class RuleCreatorMediumTest { RuleDto templateRule = createTemplateRule(); // Create custom rule - NewRule newRule = new NewRule() - .setRuleKey("CUSTOM_RULE") - .setTemplateKey(templateRule.getKey()) + NewRule newRule = NewRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey()) .setName("My custom") .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) @@ -116,9 +116,7 @@ public class RuleCreatorMediumTest { // insert template rule RuleDto templateRule = createTemplateRule(); - NewRule newRule = new NewRule() - .setRuleKey("CUSTOM_RULE") - .setTemplateKey(templateRule.getKey()) + NewRule newRule = NewRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey()) .setName("My custom") .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) @@ -136,19 +134,16 @@ public class RuleCreatorMediumTest { // insert template rule RuleDto templateRule = createTemplateRule(); - NewRule newRule = new NewRule() - .setName("My custom") - .setTemplateKey(templateRule.getKey()) - .setHtmlDescription("Some description") - .setSeverity(Severity.MAJOR) - .setStatus(RuleStatus.READY) - .setParameters(ImmutableMap.of("regex", "a.*")); - try { - creator.create(newRule); + NewRule newRule = NewRule.createForCustomRule("", templateRule.getKey()) + .setName("My custom") + .setHtmlDescription("Some description") + .setSeverity(Severity.MAJOR) + .setStatus(RuleStatus.READY) + .setParameters(ImmutableMap.of("regex", "a.*")); fail(); } catch (Exception e) { - assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("The rule key is missing"); + assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Custom key should be set"); } } @@ -157,10 +152,8 @@ public class RuleCreatorMediumTest { // insert template rule RuleDto templateRule = createTemplateRule(); - NewRule newRule = new NewRule() - .setRuleKey("*INVALID*") + NewRule newRule = NewRule.createForCustomRule("*INVALID*", templateRule.getKey()) .setName("My custom") - .setTemplateKey(templateRule.getKey()) .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) .setStatus(RuleStatus.READY) @@ -180,10 +173,8 @@ public class RuleCreatorMediumTest { RuleDto templateRule = createTemplateRule(); // Create a custom rule - NewRule newRule = new NewRule() - .setRuleKey("CUSTOM_RULE") + NewRule newRule = NewRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey()) .setName("My custom") - .setTemplateKey(templateRule.getKey()) .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) .setStatus(RuleStatus.READY) @@ -192,10 +183,8 @@ public class RuleCreatorMediumTest { try { // Create another custom rule having same key - newRule = new NewRule() - .setRuleKey("CUSTOM_RULE") + newRule = NewRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey()) .setName("My another custom") - .setTemplateKey(templateRule.getKey()) .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) .setStatus(RuleStatus.READY) @@ -212,9 +201,7 @@ public class RuleCreatorMediumTest { // insert template rule RuleDto templateRule = createTemplateRule(); - NewRule newRule = new NewRule() - .setRuleKey("CUSTOM_RULE") - .setTemplateKey(templateRule.getKey()) + NewRule newRule = NewRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey()) .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) .setStatus(RuleStatus.READY) @@ -233,9 +220,7 @@ public class RuleCreatorMediumTest { // insert template rule RuleDto templateRule = createTemplateRule(); - NewRule newRule = new NewRule() - .setRuleKey("CUSTOM_RULE") - .setTemplateKey(templateRule.getKey()) + NewRule newRule = NewRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey()) .setName("My custom") .setSeverity(Severity.MAJOR) .setStatus(RuleStatus.READY) @@ -254,9 +239,7 @@ public class RuleCreatorMediumTest { // insert template rule RuleDto templateRule = createTemplateRule(); - NewRule newRule = new NewRule() - .setRuleKey("CUSTOM_RULE") - .setTemplateKey(templateRule.getKey()) + NewRule newRule = NewRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey()) .setName("My custom") .setHtmlDescription("Some description") .setStatus(RuleStatus.READY) @@ -275,9 +258,7 @@ public class RuleCreatorMediumTest { // insert template rule RuleDto templateRule = createTemplateRule(); - NewRule newRule = new NewRule() - .setRuleKey("CUSTOM_RULE") - .setTemplateKey(templateRule.getKey()) + NewRule newRule = NewRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey()) .setName("My custom") .setHtmlDescription("Some description") .setSeverity("INVALID") @@ -297,9 +278,7 @@ public class RuleCreatorMediumTest { // insert template rule RuleDto templateRule = createTemplateRule(); - NewRule newRule = new NewRule() - .setRuleKey("CUSTOM_RULE") - .setTemplateKey(templateRule.getKey()) + NewRule newRule = NewRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey()) .setName("My custom") .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) @@ -321,9 +300,7 @@ public class RuleCreatorMediumTest { dbSession.commit(); // Create custom rule with unknown template rule - NewRule newRule = new NewRule() - .setRuleKey("CUSTOM_RULE") - .setTemplateKey(rule.getKey()) + NewRule newRule = NewRule.createForCustomRule("CUSTOM_RULE", rule.getKey()) .setName("My custom") .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) @@ -338,6 +315,154 @@ public class RuleCreatorMediumTest { } } + @Test + public void create_manual_rule() throws Exception { + NewRule newRule = NewRule.createForManualRule("MANUAL_RULE") + .setName("My manual") + .setHtmlDescription("Some description"); + RuleKey ruleKey = creator.create(newRule); + + dbSession.clearCache(); + + Rule rule = ruleIndex.getByKey(ruleKey); + assertThat(rule).isNotNull(); + assertThat(rule.key()).isEqualTo(RuleKey.of("manual", "MANUAL_RULE")); + assertThat(rule.name()).isEqualTo("My manual"); + assertThat(rule.htmlDescription()).isEqualTo("Some description"); + assertThat(rule.severity()).isNull(); + assertThat(rule.status()).isEqualTo(RuleStatus.READY); + assertThat(rule.language()).isNull(); + assertThat(rule.internalKey()).isNull(); + assertThat(rule.debtSubCharacteristicKey()).isNull(); + assertThat(rule.debtRemediationFunction()).isNull(); + assertThat(rule.tags()).isEmpty(); + assertThat(rule.systemTags()).isEmpty(); + assertThat(rule.params()).isEmpty(); + } + + @Test + public void create_manual_rule_with_severity() throws Exception { + NewRule newRule = NewRule.createForManualRule("MANUAL_RULE") + .setName("My manual") + .setHtmlDescription("Some description") + .setSeverity(Severity.BLOCKER); + RuleKey ruleKey = creator.create(newRule); + + dbSession.clearCache(); + + Rule rule = ruleIndex.getByKey(ruleKey); + assertThat(rule).isNotNull(); + assertThat(rule.key()).isEqualTo(RuleKey.of("manual", "MANUAL_RULE")); + assertThat(rule.name()).isEqualTo("My manual"); + assertThat(rule.htmlDescription()).isEqualTo("Some description"); + assertThat(rule.severity()).isEqualTo(Severity.BLOCKER); + assertThat(rule.status()).isEqualTo(RuleStatus.READY); + assertThat(rule.language()).isNull(); + assertThat(rule.internalKey()).isNull(); + assertThat(rule.debtSubCharacteristicKey()).isNull(); + assertThat(rule.debtRemediationFunction()).isNull(); + assertThat(rule.tags()).isEmpty(); + assertThat(rule.systemTags()).isEmpty(); + assertThat(rule.params()).isEmpty(); + } + + @Test + public void fail_to_create_manual_rule_when_missing_key() throws Exception { + try { + NewRule.createForManualRule("") + .setName("My manual") + .setHtmlDescription("Some description"); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Manual key should be set"); + } + } + + @Test + public void fail_to_create_manual_rule_when_invalid_key() throws Exception { + NewRule newRule = NewRule.createForManualRule("*INVALID*") + .setName("My custom") + .setHtmlDescription("Some description"); + + try { + creator.create(newRule); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("The rule key '*INVALID*' is invalid, it should only contains : a-z, 0-9, '_'"); + } + } + + @Test + public void fail_to_create_manual_rule_when_rule_key_already_exits() throws Exception { + NewRule newRule = NewRule.createForManualRule("MANUAL_RULE") + .setName("My manual") + .setHtmlDescription("Some description"); + creator.create(newRule); + + try { + // Create another rule having same key + newRule = NewRule.createForManualRule("MANUAL_RULE") + .setName("My other manual") + .setHtmlDescription("Some description"); + creator.create(newRule); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("A rule with the key 'MANUAL_RULE' already exits"); + } + } + + @Test + public void fail_to_create_manual_rule_when_missing_name() throws Exception { + NewRule newRule = NewRule.createForManualRule("MANUAL_RULE") + .setHtmlDescription("Some description"); + + try { + creator.create(newRule); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("The name is missing"); + } + } + + @Test + public void fail_to_create_manual_rule_when_missing_description() throws Exception { + NewRule newRule = NewRule.createForManualRule("MANUAL_RULE") + .setName("My manual"); + + try { + creator.create(newRule); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("The description is missing"); + } + } + + @Test + public void fail_to_create_manual_rule_with_status() throws Exception { + try { + NewRule.createForManualRule("MANUAL_RULE") + .setName("My manual") + .setHtmlDescription("Some description") + .setStatus(RuleStatus.BETA); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not a custom rule"); + } + } + + @Test + public void fail_to_create_manual_rule_with_parameters() throws Exception { + try { + NewRule.createForManualRule("MANUAL_RULE") + .setName("My manual") + .setHtmlDescription("Some description") + .setParameters(ImmutableMap.of("regex", "a.*")); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not a custom rule"); + } + } + private RuleDto createTemplateRule() { RuleDto templateRule = dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S001")) diff --git a/sonar-server/src/test/java/org/sonar/server/rule/RuleServiceMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule/RuleServiceMediumTest.java index c0c317887b9..709a297e4cb 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/RuleServiceMediumTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/RuleServiceMediumTest.java @@ -99,7 +99,7 @@ public class RuleServiceMediumTest { dao.insert(dbSession, RuleTesting.newDto(key)); dbSession.commit(); - RuleUpdate update = new RuleUpdate(key); + RuleUpdate update = RuleUpdate.createForCustomRule(key); update.setMarkdownNote("my *note*"); service.update(update); @@ -121,12 +121,12 @@ public class RuleServiceMediumTest { .setSystemTags(Sets.newHashSet("java8", "javadoc"))); dbSession.commit(); - RuleUpdate update = new RuleUpdate(key).setMarkdownNote("my *note*"); + RuleUpdate update = RuleUpdate.createForPluginRule(key).setMarkdownNote("my *note*"); service.update(update); } @Test - public void create_custom_rule() throws Exception { + public void create_rule() throws Exception { MockUserSession.set() .setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN) .setLogin("me"); @@ -137,9 +137,7 @@ public class RuleServiceMediumTest { dbSession.commit(); // Create custom rule - NewRule newRule = new NewRule() - .setRuleKey("MY_CUSTOM") - .setTemplateKey(templateRuleKey) + NewRule newRule = NewRule.createForCustomRule("MY_CUSTOM", templateRuleKey) .setName("My custom") .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) @@ -157,11 +155,11 @@ public class RuleServiceMediumTest { public void do_not_create_if_not_granted() throws Exception { MockUserSession.set().setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); - service.create(new NewRule()); + service.create(NewRule.createForCustomRule("MY_CUSTOM", RuleKey.of("java", "S001"))); } @Test - public void delete_custom_rule() throws Exception { + public void delete_rule() throws Exception { MockUserSession.set() .setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN) .setLogin("me"); @@ -172,9 +170,7 @@ public class RuleServiceMediumTest { dbSession.commit(); // Create custom rule - NewRule newRule = new NewRule() - .setRuleKey("MY_CUSTOM") - .setTemplateKey(templateRuleKey) + NewRule newRule = NewRule.createForCustomRule("MY_CUSTOM", templateRuleKey) .setName("My custom") .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) diff --git a/sonar-server/src/test/java/org/sonar/server/rule/RuleTesting.java b/sonar-server/src/test/java/org/sonar/server/rule/RuleTesting.java index c11aff6a7b7..71fbd736ea4 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/RuleTesting.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/RuleTesting.java @@ -74,4 +74,11 @@ public class RuleTesting { .setTemplateId(templateRule.getId()); } + public static RuleDto newManualRule(String manualKey){ + return new RuleDto().setRuleKey(manualKey) + .setRepositoryKey("manual") + .setDescription("Description " + manualKey) + .setStatus(RuleStatus.READY); + } + } diff --git a/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java index 08748a5b3b8..82124c640c2 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java @@ -85,7 +85,7 @@ public class RuleUpdaterMediumTest { ruleDao.insert(dbSession, RuleTesting.newDto(RULE_KEY).setStatus(RuleStatus.REMOVED)); dbSession.commit(); - RuleUpdate update = new RuleUpdate(RULE_KEY).setTags(Sets.newHashSet("java9")); + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY).setTags(Sets.newHashSet("java9")); try { updater.update(update, UserSession.get()); fail(); @@ -107,7 +107,7 @@ public class RuleUpdaterMediumTest { .setRemediationOffset("5min")); dbSession.commit(); - RuleUpdate update = new RuleUpdate(RULE_KEY); + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY); assertThat(update.isEmpty()).isTrue(); updater.update(update, UserSession.get()); @@ -138,7 +138,7 @@ public class RuleUpdaterMediumTest { .setRemediationOffset("5min")); dbSession.commit(); - RuleUpdate update = new RuleUpdate(RULE_KEY); + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY); update.setMarkdownNote("my *note*"); updater.update(update, UserSession.get()); @@ -163,7 +163,7 @@ public class RuleUpdaterMediumTest { .setNoteUserLogin("me")); dbSession.commit(); - RuleUpdate update = new RuleUpdate(RULE_KEY).setMarkdownNote(null); + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY).setMarkdownNote(null); updater.update(update, UserSession.get()); dbSession.clearCache(); @@ -183,7 +183,7 @@ public class RuleUpdaterMediumTest { dbSession.commit(); // java8 is a system tag -> ignore - RuleUpdate update = new RuleUpdate(RULE_KEY).setTags(Sets.newHashSet("bug", "java8")); + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY).setTags(Sets.newHashSet("bug", "java8")); updater.update(update, UserSession.get()); dbSession.clearCache(); @@ -203,7 +203,7 @@ public class RuleUpdaterMediumTest { .setSystemTags(Sets.newHashSet("java8", "javadoc"))); dbSession.commit(); - RuleUpdate update = new RuleUpdate(RULE_KEY).setTags(null); + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY).setTags(null); updater.update(update, UserSession.get()); dbSession.clearCache(); @@ -230,7 +230,7 @@ public class RuleUpdaterMediumTest { dbSession.commit(); DefaultDebtRemediationFunction fn = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, null, "1min"); - RuleUpdate update = new RuleUpdate(RULE_KEY) + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) .setDebtSubCharacteristic("SOFT_RELIABILITY") .setDebtRemediationFunction(fn); updater.update(update, UserSession.get()); @@ -266,7 +266,7 @@ public class RuleUpdaterMediumTest { .setRemediationOffset("1min")); dbSession.commit(); - RuleUpdate update = new RuleUpdate(RULE_KEY) + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) .setDebtSubCharacteristic(RuleUpdate.DEFAULT_DEBT_CHARACTERISTIC); updater.update(update, UserSession.get()); @@ -301,7 +301,7 @@ public class RuleUpdaterMediumTest { .setRemediationOffset("1min")); dbSession.commit(); - RuleUpdate update = new RuleUpdate(RULE_KEY) + RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) .setDebtSubCharacteristic(null); updater.update(update, UserSession.get()); @@ -425,6 +425,125 @@ public class RuleUpdaterMediumTest { assertThat(activeRule.severity()).isEqualTo(Severity.BLOCKER); } + @Test + public void update_manual_rule() throws Exception { + // Create manual rule + RuleDto manualRule = RuleTesting.newManualRule("My manual") + .setName("Old name") + .setDescription("Old description") + .setSeverity(Severity.INFO); + ruleDao.insert(dbSession, manualRule); + + dbSession.commit(); + + // Update manual rule + RuleUpdate update = RuleUpdate.createForManualRule(manualRule.getKey()) + .setName("New name") + .setHtmlDescription("New description") + .setSeverity(Severity.CRITICAL); + updater.update(update, UserSession.get()); + + dbSession.clearCache(); + + // Verify manual rule is updated + Rule manualRuleReloaded = ruleIndex.getByKey(manualRule.getKey()); + assertThat(manualRuleReloaded).isNotNull(); + assertThat(manualRuleReloaded.name()).isEqualTo("New name"); + assertThat(manualRuleReloaded.htmlDescription()).isEqualTo("New description"); + assertThat(manualRuleReloaded.severity()).isEqualTo(Severity.CRITICAL); + } + + @Test + public void fail_to_update_manual_rule_if_status_is_set() throws Exception { + // Create manual rule + RuleDto manualRule = RuleTesting.newManualRule("My manual"); + ruleDao.insert(dbSession, manualRule); + + dbSession.commit(); + + try { + // Update manual rule + RuleUpdate.createForManualRule(manualRule.getKey()) + .setStatus(RuleStatus.BETA); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not a custom rule"); + } + } + + @Test + public void fail_to_update_manual_rule_if_parameters_are_set() throws Exception { + // Create manual rule + RuleDto manualRule = RuleTesting.newManualRule("My manual"); + ruleDao.insert(dbSession, manualRule); + + dbSession.commit(); + + try { + // Update manual rule + RuleUpdate.createForManualRule(manualRule.getKey()) + .setStatus(RuleStatus.BETA) + .setParameters(ImmutableMap.of("regex", "b.*", "message", "a message")); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not a custom rule"); + } + } + + @Test + public void fail_to_update_plugin_rule_if_name_is_set() throws Exception { + // Create rule rule + RuleDto ruleDto = RuleTesting.newDto(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 or a manual rule"); + } + } + + @Test + public void fail_to_update_plugin_rule_if_description_is_set() throws Exception { + // Create rule rule + RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("squid", "S01")); + ruleDao.insert(dbSession, ruleDto); + + dbSession.commit(); + + try { + // Update rule + RuleUpdate.createForPluginRule(ruleDto.getKey()) + .setHtmlDescription("New description"); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Not a custom or a manual rule"); + } + } + + @Test + public void fail_to_update_plugin_rule_if_severity_is_set() throws Exception { + // Create rule rule + RuleDto ruleDto = RuleTesting.newDto(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 or a manual rule"); + } + } + private void insertDebtCharacteristics(DbSession dbSession) { CharacteristicDto reliability = DebtTesting.newCharacteristicDto("RELIABILITY"); db.debtCharacteristicDao().insert(reliability, dbSession); diff --git a/sonar-server/src/test/java/org/sonar/server/rule/ws/CreateActionMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule/ws/CreateActionMediumTest.java index fb074ecdcc1..1c84857326b 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/ws/CreateActionMediumTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/ws/CreateActionMediumTest.java @@ -32,6 +32,7 @@ import org.sonar.core.persistence.DbSession; import org.sonar.core.rule.RuleDto; import org.sonar.core.rule.RuleParamDto; import org.sonar.server.db.DbClient; +import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.rule.RuleService; import org.sonar.server.rule.RuleTesting; import org.sonar.server.rule.db.RuleDao; @@ -39,6 +40,9 @@ import org.sonar.server.tester.ServerTester; import org.sonar.server.user.MockUserSession; import org.sonar.server.ws.WsTester; +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.Fail.fail; + @RunWith(MockitoJUnitRunner.class) public class CreateActionMediumTest { @@ -78,7 +82,7 @@ public class CreateActionMediumTest { session.commit(); WsTester.TestRequest request = wsTester.newGetRequest("api/rules", "create") - .setParam("key", "MY_CUSTOM") + .setParam("custom_key", "MY_CUSTOM") .setParam("template_key", templateRule.getKey().toString()) .setParam("name", "My custom rule") .setParam("html_description", "Description") @@ -88,4 +92,51 @@ public class CreateActionMediumTest { request.execute().assertJson(getClass(), "create_custom_rule.json", false); } + @Test + public void create_manual_rule() throws Exception { + MockUserSession.set() + .setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN) + .setLogin("me"); + + WsTester.TestRequest request = wsTester.newGetRequest("api/rules", "create") + .setParam("manual_key", "MY_MANUAL") + .setParam("name", "My manual rule") + .setParam("html_description", "Description") + .setParam("severity", "MAJOR"); + request.execute().assertJson(getClass(), "create_manual_rule.json", false); + } + + @Test + public void create_manual_rule_without_severity() throws Exception { + MockUserSession.set() + .setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN) + .setLogin("me"); + + WsTester.TestRequest request = wsTester.newGetRequest("api/rules", "create") + .setParam("manual_key", "MY_MANUAL") + .setParam("name", "My manual rule") + .setParam("html_description", "Description"); + request.execute().assertJson(getClass(), "create_manual_rule_without_severity.json", false); + } + + @Test + public void fail_if_custom_key_and_manual_key_parameters_are_not_set() throws Exception { + MockUserSession.set() + .setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN) + .setLogin("me"); + + WsTester.TestRequest request = wsTester.newGetRequest("api/rules", "create") + .setParam("key", "MY_MANUAL") + .setParam("name", "My manual rule") + .setParam("html_description", "Description") + .setParam("severity", "MAJOR"); + + try { + request.execute(); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("Either 'custom_key' or 'manual_key' parameters should be set"); + } + } + } diff --git a/sonar-server/src/test/java/org/sonar/server/rule/ws/UpdateActionMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule/ws/UpdateActionMediumTest.java index 1ca8956e27f..8d241c2b315 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/ws/UpdateActionMediumTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/ws/UpdateActionMediumTest.java @@ -82,9 +82,7 @@ public class UpdateActionMediumTest { session.commit(); // Custom rule - NewRule newRule = new NewRule() - .setRuleKey("MY_CUSTOM") - .setTemplateKey(templateRule.getKey()) + NewRule newRule = NewRule.createForCustomRule("MY_CUSTOM", templateRule.getKey()) .setName("Old custom") .setHtmlDescription("Old description") .setSeverity(Severity.MINOR) diff --git a/sonar-server/src/test/resources/org/sonar/server/rule/ws/CreateActionMediumTest/create_manual_rule.json b/sonar-server/src/test/resources/org/sonar/server/rule/ws/CreateActionMediumTest/create_manual_rule.json new file mode 100644 index 00000000000..a78fb0fadf3 --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/rule/ws/CreateActionMediumTest/create_manual_rule.json @@ -0,0 +1,14 @@ +{ + "rule": { + "key": "manual:MY_MANUAL", + "repo": "manual", + "name": "My manual rule", + "htmlDesc": "Description", + "severity": "MAJOR", + "status": "READY", + "isTemplate": false, + "tags": [], + "sysTags": [], + "params": [] + } +} diff --git a/sonar-server/src/test/resources/org/sonar/server/rule/ws/CreateActionMediumTest/create_manual_rule_without_severity.json b/sonar-server/src/test/resources/org/sonar/server/rule/ws/CreateActionMediumTest/create_manual_rule_without_severity.json new file mode 100644 index 00000000000..0f0e195298e --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/rule/ws/CreateActionMediumTest/create_manual_rule_without_severity.json @@ -0,0 +1,13 @@ +{ + "rule": { + "key": "manual:MY_MANUAL", + "repo": "manual", + "name": "My manual rule", + "htmlDesc": "Description", + "status": "READY", + "isTemplate": false, + "tags": [], + "sysTags": [], + "params": [] + } +} -- 2.39.5