aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-webserver-webapi
diff options
context:
space:
mode:
authorZipeng WU <zipeng.wu@sonarsource.com>2022-04-26 10:49:06 +0200
committersonartech <sonartech@sonarsource.com>2022-05-06 20:02:43 +0000
commit6bb200a692f7a200c0ca27900c24c8c89982e521 (patch)
tree6a4a5c604c60dcbfc555c541e29f8f5d1cab97a2 /server/sonar-webserver-webapi
parent838c48d8e94d0d780582cdfb4429e5cb57615f6f (diff)
downloadsonarqube-6bb200a692f7a200c0ca27900c24c8c89982e521.tar.gz
sonarqube-6bb200a692f7a200c0ca27900c24c8c89982e521.zip
SONAR-16302 Adapt ExportRuleDto to handle new structure
Diffstat (limited to 'server/sonar-webserver-webapi')
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ImportedRule.java48
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuperImpl.java20
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java101
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/NewCustomRule.java31
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/NewRuleDescriptionSection.java39
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleCreator.java23
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/ShowActionTest.java2
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperImplTest.java29
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileParserTest.java86
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/RuleCreatorTest.java187
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/ListActionTest.java31
11 files changed, 435 insertions, 162 deletions
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ImportedRule.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ImportedRule.java
index be99ea779a7..a9d2e60c01e 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ImportedRule.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ImportedRule.java
@@ -19,28 +19,34 @@
*/
package org.sonar.server.qualityprofile;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import org.sonar.api.rule.RuleKey;
+import org.sonar.server.rule.NewRuleDescriptionSection;
class ImportedRule {
- private RuleKey ruleKey = null;
- private RuleKey templateKey = null;
+ private String key = null;
+
+ private String repository = null;
+
+ private String template = null;
private String name = null;
private String type = null;
private String severity = null;
private String description = null;
private Map<String, String> parameters = null;
-
+ private Set<NewRuleDescriptionSection> ruleDescriptionSections = new HashSet<>();
public Map<String, String> getParameters() {
return parameters;
}
public RuleKey getRuleKey() {
- return ruleKey;
+ return RuleKey.of(repository, key);
}
public RuleKey getTemplateKey() {
- return templateKey;
+ return RuleKey.of(repository, template);
}
public String getName() {
@@ -59,16 +65,6 @@ class ImportedRule {
return description;
}
- ImportedRule setRuleKey(RuleKey ruleKey) {
- this.ruleKey = ruleKey;
- return this;
- }
-
- ImportedRule setTemplateKey(RuleKey templateKey) {
- this.templateKey = templateKey;
- return this;
- }
-
ImportedRule setType(String type) {
this.type = type;
return this;
@@ -95,6 +91,26 @@ class ImportedRule {
}
boolean isCustomRule() {
- return templateKey != null;
+ return template != null;
+ }
+
+ public Set<NewRuleDescriptionSection> getRuleDescriptionSections() {
+ return ruleDescriptionSections;
+ }
+
+ public void addRuleDescriptionSection(NewRuleDescriptionSection ruleDescriptionSection) {
+ this.ruleDescriptionSections.add(ruleDescriptionSection);
+ }
+
+ public void setRepository(String repository) {
+ this.repository = repository;
+ }
+
+ public void setTemplate(String template) {
+ this.template = template;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
}
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuperImpl.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuperImpl.java
index 30dffad218e..de4bbb89cf6 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuperImpl.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuperImpl.java
@@ -45,10 +45,12 @@ import org.sonar.db.rule.DeprecatedRuleKeyDto;
import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.server.qualityprofile.builtin.QProfileName;
import org.sonar.server.rule.NewCustomRule;
+import org.sonar.server.rule.NewRuleDescriptionSection;
import org.sonar.server.rule.RuleCreator;
import static com.google.common.base.Preconditions.checkArgument;
import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.toSet;
@ServerSide
public class QProfileBackuperImpl implements QProfileBackuper {
@@ -88,15 +90,20 @@ public class QProfileBackuperImpl implements QProfileBackuper {
List<ImportedRule> importedRules = new ArrayList<>(exportRules.size());
for (ExportRuleDto exportRuleDto : exportRules) {
+ var ruleKey = exportRuleDto.getRuleKey();
ImportedRule importedRule = new ImportedRule();
importedRule.setName(exportRuleDto.getName());
- importedRule.setDescription(exportRuleDto.getDescription());
- importedRule.setRuleKey(exportRuleDto.getRuleKey());
+ importedRule.setRepository(ruleKey.repository());
+ importedRule.setKey(ruleKey.rule());
importedRule.setSeverity(exportRuleDto.getSeverityString());
if (importedRule.isCustomRule()) {
- importedRule.setTemplateKey(exportRuleDto.getTemplateRuleKey());
+ importedRule.setTemplate(exportRuleDto.getTemplateRuleKey().rule());
}
importedRule.setType(exportRuleDto.getRuleType().name());
+ exportRuleDto.getRuleDescriptionSections()
+ .stream()
+ .map(r -> new NewRuleDescriptionSection(r.getKey(), r.getDescription()))
+ .forEach(importedRule::addRuleDescriptionSection);
importedRule.setParameters(exportRuleDto.getParams().stream().collect(Collectors.toMap(ExportRuleParamDto::getKey, ExportRuleParamDto::getValue)));
importedRules.add(importedRule);
}
@@ -154,13 +161,13 @@ public class QProfileBackuperImpl implements QProfileBackuper {
private Map<RuleKey, RuleDefinitionDto> getImportedRulesDefinitions(DbSession dbSession, List<ImportedRule> rules) {
Set<RuleKey> ruleKeys = rules.stream()
.map(ImportedRule::getRuleKey)
- .collect(Collectors.toSet());
+ .collect(toSet());
Map<RuleKey, RuleDefinitionDto> rulesDefinitions = db.ruleDao().selectDefinitionByKeys(dbSession, ruleKeys).stream()
.collect(Collectors.toMap(RuleDefinitionDto::getKey, identity()));
Set<RuleKey> unrecognizedRuleKeys = ruleKeys.stream()
.filter(r -> !rulesDefinitions.containsKey(r))
- .collect(Collectors.toSet());
+ .collect(toSet());
if (!unrecognizedRuleKeys.isEmpty()) {
Map<String, DeprecatedRuleKeyDto> deprecatedRuleKeysByUuid = db.ruleDao().selectAllDeprecatedRuleKeys(dbSession).stream()
@@ -209,11 +216,12 @@ public class QProfileBackuperImpl implements QProfileBackuper {
private static NewCustomRule importedRuleToNewCustomRule(ImportedRule r) {
return NewCustomRule.createForCustomRule(r.getRuleKey().rule(), r.getTemplateKey())
.setName(r.getName())
- .setMarkdownDescription(r.getDescription())
.setSeverity(r.getSeverity())
.setStatus(RuleStatus.READY)
.setPreventReactivation(true)
.setType(RuleType.valueOf(r.getType()))
+ .setMarkdownDescription(r.getDescription())
+ .setRuleDescriptionSections(r.getRuleDescriptionSections())
.setParameters(r.getParameters());
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java
index 7ea8fd88198..f345d2fc4d4 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java
@@ -42,15 +42,20 @@ import org.sonar.api.utils.text.XmlWriter;
import org.sonar.db.qualityprofile.ExportRuleDto;
import org.sonar.db.qualityprofile.ExportRuleParamDto;
import org.sonar.db.qualityprofile.QProfileDto;
+import org.sonar.db.rule.RuleDescriptionSectionDto;
+import org.sonar.server.rule.NewRuleDescriptionSection;
@ServerSide
public class QProfileParser {
private static final String ATTRIBUTE_PROFILE = "profile";
private static final String ATTRIBUTE_NAME = "name";
private static final String ATTRIBUTE_LANGUAGE = "language";
-
private static final String ATTRIBUTE_RULES = "rules";
private static final String ATTRIBUTE_RULE = "rule";
+ private static final String ATTRIBUTE_DESCRIPTION_SECTIONS = "descriptionSections";
+ private static final String ATTRIBUTE_DESCRIPTION_SECTION = "descriptionSection";
+ private static final String ATTRIBUTE_DESCRIPTION_SECTION_KEY = "key";
+ private static final String ATTRIBUTE_DESCRIPTION_SECTION_DESCRIPTION = "content";
private static final String ATTRIBUTE_REPOSITORY_KEY = "repositoryKey";
private static final String ATTRIBUTE_KEY = "key";
private static final String ATTRIBUTE_PRIORITY = "priority";
@@ -80,7 +85,19 @@ public class QProfileParser {
if (ruleToExport.isCustomRule()) {
xml.prop(ATTRIBUTE_NAME, ruleToExport.getName());
xml.prop(ATTRIBUTE_TEMPLATE_KEY, ruleToExport.getTemplateRuleKey().rule());
- xml.prop(ATTRIBUTE_DESCRIPTION, ruleToExport.getDescription());
+ if (!ruleToExport.getRuleDescriptionSections().isEmpty()) {
+ ruleToExport.getDefaultRuleDescriptionSectionDto()
+ .map(RuleDescriptionSectionDto::getDescription)
+ .ifPresent(desc -> xml.prop(ATTRIBUTE_DESCRIPTION, desc));
+ }
+ xml.begin(ATTRIBUTE_DESCRIPTION_SECTIONS);
+ for (RuleDescriptionSectionDto ruleDescriptionSection : ruleToExport.getRuleDescriptionSections()) {
+ xml.begin(ATTRIBUTE_DESCRIPTION_SECTION)
+ .prop(ATTRIBUTE_DESCRIPTION_SECTION_KEY, ruleDescriptionSection.getKey())
+ .prop(ATTRIBUTE_DESCRIPTION_SECTION_DESCRIPTION, ruleDescriptionSection.getDescription())
+ .end();
+ }
+ xml.end(ATTRIBUTE_DESCRIPTION_SECTIONS);
}
xml.begin(ATTRIBUTE_PARAMETERS);
@@ -144,39 +161,10 @@ public class QProfileParser {
while (rulesCursor.getNext() != null) {
SMInputCursor ruleCursor = rulesCursor.childElementCursor();
Map<String, String> parameters = new HashMap<>();
- String repositoryKey = null;
- String key = null;
- String templateKey = null;
ImportedRule rule = new ImportedRule();
- while (ruleCursor.getNext() != null) {
- String nodeName = ruleCursor.getLocalName();
- if (StringUtils.equals(ATTRIBUTE_REPOSITORY_KEY, nodeName)) {
- repositoryKey = StringUtils.trim(ruleCursor.collectDescendantText(false));
- } else if (StringUtils.equals(ATTRIBUTE_KEY, nodeName)) {
- key = StringUtils.trim(ruleCursor.collectDescendantText(false));
- } else if (StringUtils.equals(ATTRIBUTE_TEMPLATE_KEY, nodeName)) {
- templateKey = StringUtils.trim(ruleCursor.collectDescendantText(false));
- } else if (StringUtils.equals(ATTRIBUTE_NAME, nodeName)) {
- rule.setName(StringUtils.trim(ruleCursor.collectDescendantText(false)));
- } else if (StringUtils.equals(ATTRIBUTE_TYPE, nodeName)) {
- rule.setType(StringUtils.trim(ruleCursor.collectDescendantText(false)));
- } else if (StringUtils.equals(ATTRIBUTE_DESCRIPTION, nodeName)) {
- rule.setDescription(StringUtils.trim(ruleCursor.collectDescendantText(false)));
- } else if (StringUtils.equals(ATTRIBUTE_PRIORITY, nodeName)) {
- rule.setSeverity(StringUtils.trim(ruleCursor.collectDescendantText(false)));
- } else if (StringUtils.equals(ATTRIBUTE_PARAMETERS, nodeName)) {
- SMInputCursor propsCursor = ruleCursor.childElementCursor(ATTRIBUTE_PARAMETER);
- readParameters(propsCursor, parameters);
- rule.setParameters(parameters);
- }
- }
- RuleKey ruleKey = RuleKey.of(repositoryKey, key);
- rule.setRuleKey(ruleKey);
-
- if (templateKey != null) {
- rule.setTemplateKey(RuleKey.of(repositoryKey, templateKey));
- }
+ readRule(ruleCursor, parameters, rule);
+ var ruleKey = rule.getRuleKey();
if (activatedKeys.contains(ruleKey)) {
duplicatedKeys.add(ruleKey);
}
@@ -190,6 +178,34 @@ public class QProfileParser {
return activations;
}
+ private static void readRule(SMInputCursor ruleCursor, Map<String, String> parameters, ImportedRule rule) throws XMLStreamException {
+ while (ruleCursor.getNext() != null) {
+ String nodeName = ruleCursor.getLocalName();
+ if (StringUtils.equals(ATTRIBUTE_REPOSITORY_KEY, nodeName)) {
+ rule.setRepository(StringUtils.trim(ruleCursor.collectDescendantText(false)));
+ } else if (StringUtils.equals(ATTRIBUTE_KEY, nodeName)) {
+ rule.setKey(StringUtils.trim(ruleCursor.collectDescendantText(false)));
+ } else if (StringUtils.equals(ATTRIBUTE_TEMPLATE_KEY, nodeName)) {
+ rule.setTemplate(StringUtils.trim(ruleCursor.collectDescendantText(false)));
+ } else if (StringUtils.equals(ATTRIBUTE_NAME, nodeName)) {
+ rule.setName(StringUtils.trim(ruleCursor.collectDescendantText(false)));
+ } else if (StringUtils.equals(ATTRIBUTE_TYPE, nodeName)) {
+ rule.setType(StringUtils.trim(ruleCursor.collectDescendantText(false)));
+ } else if (StringUtils.equals(ATTRIBUTE_DESCRIPTION, nodeName)) {
+ rule.setDescription(StringUtils.trim(ruleCursor.collectDescendantText(false)));
+ } else if (StringUtils.equals(ATTRIBUTE_PRIORITY, nodeName)) {
+ rule.setSeverity(StringUtils.trim(ruleCursor.collectDescendantText(false)));
+ } else if (StringUtils.equals(ATTRIBUTE_PARAMETERS, nodeName)) {
+ SMInputCursor propsCursor = ruleCursor.childElementCursor(ATTRIBUTE_PARAMETER);
+ readParameters(propsCursor, parameters);
+ rule.setParameters(parameters);
+ } else if (StringUtils.equals(ATTRIBUTE_DESCRIPTION_SECTIONS, nodeName)) {
+ SMInputCursor propsCursor = ruleCursor.childElementCursor(ATTRIBUTE_DESCRIPTION_SECTION);
+ readDescriptionSections(propsCursor, rule);
+ }
+ }
+ }
+
private static void readParameters(SMInputCursor propsCursor, Map<String, String> parameters) throws XMLStreamException {
while (propsCursor.getNext() != null) {
SMInputCursor propCursor = propsCursor.childElementCursor();
@@ -208,4 +224,23 @@ public class QProfileParser {
}
}
}
+
+ private static void readDescriptionSections(SMInputCursor propsCursor, ImportedRule importedRule) throws XMLStreamException {
+ while (propsCursor.getNext() != null) {
+ SMInputCursor propCursor = propsCursor.childElementCursor();
+ String key = null;
+ String description = null;
+ while (propCursor.getNext() != null) {
+ String nodeName = propCursor.getLocalName();
+ if (StringUtils.equals(ATTRIBUTE_DESCRIPTION_SECTION_KEY, nodeName)) {
+ key = StringUtils.trim(propCursor.collectDescendantText(false));
+ } else if (StringUtils.equals(ATTRIBUTE_DESCRIPTION_SECTION_DESCRIPTION, nodeName)) {
+ description = StringUtils.trim(propCursor.collectDescendantText(false));
+ }
+ }
+ if (key != null && description != null) {
+ importedRule.addRuleDescriptionSection(new NewRuleDescriptionSection(key, description));
+ }
+ }
+ }
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/NewCustomRule.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/NewCustomRule.java
index a803ede0bfc..d824eb92769 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/NewCustomRule.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/NewCustomRule.java
@@ -21,8 +21,11 @@ package org.sonar.server.rule;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.api.rule.RuleKey;
@@ -34,12 +37,13 @@ public class NewCustomRule {
private String ruleKey;
private RuleKey templateKey;
private String name;
- private String htmlDescription;
private String markdownDescription;
private String severity;
private RuleStatus status;
private RuleType type;
- private final Map<String, String> parameters = new HashMap<>();
+ private Map<String, String> parameters = new HashMap<>();
+
+ private Set<NewRuleDescriptionSection> ruleDescriptionSections = new HashSet<>();
private boolean preventReactivation = false;
@@ -67,16 +71,6 @@ public class NewCustomRule {
}
@CheckForNull
- public String htmlDescription() {
- return htmlDescription;
- }
-
- public NewCustomRule setHtmlDescription(@Nullable String htmlDescription) {
- this.htmlDescription = htmlDescription;
- return this;
- }
-
- @CheckForNull
public String markdownDescription() {
return markdownDescription;
}
@@ -122,8 +116,16 @@ public class NewCustomRule {
}
public NewCustomRule setParameters(Map<String, String> params) {
- this.parameters.clear();
- this.parameters.putAll(params);
+ this.parameters = params;
+ return this;
+ }
+
+ public Set<NewRuleDescriptionSection> getRuleDescriptionSections() {
+ return Collections.unmodifiableSet(ruleDescriptionSections);
+ }
+
+ public NewCustomRule setRuleDescriptionSections(Set<NewRuleDescriptionSection> sections) {
+ this.ruleDescriptionSections = sections;
return this;
}
@@ -147,5 +149,4 @@ public class NewCustomRule {
newRule.templateKey = templateKey;
return newRule;
}
-
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/NewRuleDescriptionSection.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/NewRuleDescriptionSection.java
new file mode 100644
index 00000000000..081262028d2
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/NewRuleDescriptionSection.java
@@ -0,0 +1,39 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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;
+
+public class NewRuleDescriptionSection {
+ private final String key;
+
+ private final String description;
+
+ public NewRuleDescriptionSection(String key, String description) {
+ this.key = key;
+ this.description = description;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleCreator.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleCreator.java
index b7d321877a7..4b36e35c7f6 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleCreator.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleCreator.java
@@ -168,11 +168,18 @@ public class RuleCreator {
}
private static void validateDescription(List<String> errors, NewCustomRule newRule) {
- if (Strings.isNullOrEmpty(newRule.htmlDescription()) && Strings.isNullOrEmpty(newRule.markdownDescription())) {
+ boolean missingDescription = newRule.getRuleDescriptionSections().isEmpty() ?
+ Strings.isNullOrEmpty(newRule.markdownDescription()) :
+ noDescriptionSectionHasContent(newRule);
+ if (missingDescription) {
errors.add("The description is missing");
}
}
+ private static boolean noDescriptionSectionHasContent(NewCustomRule newRule) {
+ return newRule.getRuleDescriptionSections().stream().map(NewRuleDescriptionSection::getDescription).allMatch(Strings::isNullOrEmpty);
+ }
+
private static void validateRuleKey(List<String> errors, String ruleKey) {
if (!ruleKey.matches("^[\\w]+$")) {
errors.add(format("The rule key \"%s\" is invalid, it should only contain: a-z, 0-9, \"_\"", ruleKey));
@@ -207,10 +214,20 @@ public class RuleCreator {
.setCreatedAt(system2.now())
.setUpdatedAt(system2.now());
- if (newRule.markdownDescription() != null) {
+ ruleDefinition.setDescriptionFormat(Format.MARKDOWN);
+
+ if (newRule.getRuleDescriptionSections().isEmpty() && newRule.markdownDescription() != null) {
RuleDescriptionSectionDto ruleDescriptionSectionDto = createDefaultRuleDescriptionSection(uuidFactory.create(), newRule.markdownDescription());
- ruleDefinition.setDescriptionFormat(Format.MARKDOWN);
ruleDefinition.addRuleDescriptionSectionDto(ruleDescriptionSectionDto);
+ } else {
+ for (NewRuleDescriptionSection ruleDescriptionSection : newRule.getRuleDescriptionSections()) {
+ RuleDescriptionSectionDto ruleDescriptionSectionDto = RuleDescriptionSectionDto.builder()
+ .uuid(uuidFactory.create())
+ .key(ruleDescriptionSection.getKey())
+ .description(ruleDescriptionSection.getDescription())
+ .build();
+ ruleDefinition.addRuleDescriptionSectionDto(ruleDescriptionSectionDto);
+ }
}
dbClient.ruleDao().insert(dbSession, ruleDefinition);
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/ShowActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/ShowActionTest.java
index d791c487edc..ec3a28866ac 100644
--- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/ShowActionTest.java
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/ShowActionTest.java
@@ -1033,7 +1033,7 @@ public class ShowActionTest {
}
private RuleDefinitionDto newRuleWithoutSection(RuleType ruleType, Consumer<RuleDefinitionDto> populate) {
- return newRule(ruleType, RuleTesting::newRuleWithoutSection, populate);
+ return newRule(ruleType, RuleTesting::newRuleWithoutDescriptionSection, populate);
}
private RuleDefinitionDto newRule(RuleType ruleType, Supplier<RuleDefinitionDto> ruleDefinitionDtoSupplier, Consumer<RuleDefinitionDto> populate) {
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperImplTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperImplTest.java
index 08e74098b12..542424a8661 100644
--- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperImplTest.java
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperImplTest.java
@@ -56,6 +56,7 @@ import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.db.rule.RuleDescriptionSectionDto.createDefaultRuleDescriptionSection;
+import static org.sonar.db.rule.RuleTesting.newRuleWithoutDescriptionSection;
public class QProfileBackuperImplTest {
@@ -166,6 +167,34 @@ public class QProfileBackuperImplTest {
"<name>" + rule.getName() + "</name>" +
"<templateKey>" + templateRule.getKey().rule() + "</templateKey>" +
"<description>" + rule.getDefaultRuleDescriptionSectionDto().getDescription() + "</description>" +
+ "<descriptionSections><descriptionSection><key>default</key><content>" + rule.getDefaultRuleDescriptionSectionDto().getDescription() + "</content></descriptionSection></descriptionSections>" +
+ "<parameters><parameter>" +
+ "<key>" + param.getName() + "</key>" +
+ "<value>20</value>" +
+ "</parameter></parameters>" +
+ "</rule></rules></profile>");
+ }
+
+ @Test
+ public void backup_custom_rules_without_description_section() {
+ var rule = newRuleWithoutDescriptionSection();
+ db.rules().insert(rule);
+ RuleParamDto param = db.rules().insertRuleParam(rule);
+ QProfileDto profile = createProfile(rule.getLanguage());
+ ActiveRuleDto activeRule = activate(profile, rule, param);
+
+ StringWriter writer = new StringWriter();
+ underTest.backup(db.getSession(), profile, writer);
+
+ assertThat(writer).hasToString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+ "<profile>" +
+ "<name>" + profile.getName() + "</name>" +
+ "<language>" + profile.getLanguage() + "</language>" +
+ "<rules><rule>" +
+ "<repositoryKey>" + rule.getRepositoryKey() + "</repositoryKey>" +
+ "<key>" + rule.getKey().rule() + "</key>" +
+ "<type>" + RuleType.valueOf(rule.getType()) + "</type>" +
+ "<priority>" + activeRule.getSeverityString() + "</priority>" +
"<parameters><parameter>" +
"<key>" + param.getName() + "</key>" +
"<value>20</value>" +
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileParserTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileParserTest.java
new file mode 100644
index 00000000000..aab08268815
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileParserTest.java
@@ -0,0 +1,86 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.qualityprofile;
+
+import java.io.Reader;
+import java.io.StringReader;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class QProfileParserTest {
+
+ @Test
+ public void readOlderVersionXml() {
+ Reader backup = new StringReader("<?xml version='1.0' encoding='UTF-8'?>" +
+ "<profile>" +
+ "<name>custom rule</name>" +
+ "<language>js</language>" +
+ "<rules><rule>" +
+ "<repositoryKey>sonarjs</repositoryKey>" +
+ "<key>s001</key>" +
+ "<type>CODE_SMELL</type>" +
+ "<priority>CRITICAL</priority>" +
+ "<name>custom rule name</name>" +
+ "<templateKey>rule_mc8</templateKey>" +
+ "<description>custom rule description</description>" +
+ "<parameters><parameter>" +
+ "<key>bar</key>" +
+ "<value>baz</value>" +
+ "</parameter>" +
+ "</parameters>" +
+ "</rule></rules></profile>");
+ var parser = new QProfileParser();
+ var importedQProfile = parser.readXml(backup);
+ assertThat(importedQProfile.getRules()).hasSize(1);
+ var importedRule = importedQProfile.getRules().get(0);
+ assertThat(importedRule.getDescription()).isEqualTo("custom rule description");
+ }
+
+ @Test
+ public void readNewVersionXml() {
+ Reader backup = new StringReader("<?xml version='1.0' encoding='UTF-8'?>" +
+ "<profile>" +
+ "<name>custom rule</name>" +
+ "<language>js</language>" +
+ "<rules><rule>" +
+ "<repositoryKey>sonarjs</repositoryKey>" +
+ "<key>s001</key>" +
+ "<type>CODE_SMELL</type>" +
+ "<priority>CRITICAL</priority>" +
+ "<name>custom rule name</name>" +
+ "<templateKey>rule_mc8</templateKey>" +
+ "<descriptionSections><descriptionSection><key>default</key><content>custom rule description</content></descriptionSection></descriptionSections>" +
+ "<parameters><parameter>" +
+ "<key>bar</key>" +
+ "<value>baz</value>" +
+ "</parameter>" +
+ "</parameters>" +
+ "</rule></rules></profile>");
+ var parser = new QProfileParser();
+ var importedQProfile = parser.readXml(backup);
+ assertThat(importedQProfile.getRules()).hasSize(1);
+ var importedRule = importedQProfile.getRules().get(0);
+ assertThat(importedRule.getRuleDescriptionSections()).hasSize(1);
+ var section = importedRule.getRuleDescriptionSections().iterator().next();
+ assertThat(section.getKey()).isEqualTo("default");
+ assertThat(section.getDescription()).isEqualTo("custom rule description");
+ }
+}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/RuleCreatorTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/RuleCreatorTest.java
index 082fe1de06a..428f4d4ed04 100644
--- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/RuleCreatorTest.java
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/RuleCreatorTest.java
@@ -26,6 +26,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import org.assertj.core.api.Fail;
import org.junit.Rule;
@@ -63,7 +64,6 @@ public class RuleCreatorTest {
private System2 system2 = new TestSystem2().setNow(Instant.now().toEpochMilli());
-
@Rule
public DbTester dbTester = DbTester.create(system2);
@@ -126,12 +126,48 @@ public class RuleCreatorTest {
}
@Test
+ public void create_custom_rule_with_both_markdown_description_and_description_sections() {
+ // insert template rule
+ RuleDto templateRule = createTemplateRule();
+ // Create custom rule
+ NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
+ .setName("My custom")
+ .setMarkdownDescription("Markdown description")
+ .setRuleDescriptionSections(Set.of(new NewRuleDescriptionSection("default", "new description section")))
+ .setSeverity(Severity.MAJOR)
+ .setStatus(RuleStatus.READY);
+ RuleKey customRuleKey = underTest.create(dbSession, newRule);
+
+ RuleDto rule = dbTester.getDbClient().ruleDao().selectOrFailByKey(dbSession, customRuleKey);
+ assertThat(rule).isNotNull();
+ assertThat(rule.getKey()).isEqualTo(RuleKey.of("java", "CUSTOM_RULE"));
+ assertThat(rule.getPluginKey()).isEqualTo("sonarjava");
+ assertThat(rule.getTemplateUuid()).isEqualTo(templateRule.getUuid());
+ assertThat(rule.getName()).isEqualTo("My custom");
+ assertThat(rule.getDefaultRuleDescriptionSection().getDescription()).isEqualTo("new description section");
+ assertThat(rule.getSeverityString()).isEqualTo("MAJOR");
+ assertThat(rule.getStatus()).isEqualTo(RuleStatus.READY);
+ assertThat(rule.getLanguage()).isEqualTo("java");
+ assertThat(rule.getConfigKey()).isEqualTo("S001");
+ assertThat(rule.getDefRemediationFunction()).isEqualTo("LINEAR_OFFSET");
+ assertThat(rule.getDefRemediationGapMultiplier()).isEqualTo("1h");
+ assertThat(rule.getDefRemediationBaseEffort()).isEqualTo("5min");
+ assertThat(rule.getGapDescription()).isEqualTo("desc");
+ assertThat(rule.getTags()).containsOnly("usertag1", "usertag2");
+ assertThat(rule.getSystemTags()).containsOnly("tag1", "tag4");
+ assertThat(rule.getSecurityStandards()).containsOnly("owaspTop10:a1", "cwe:123");
+ assertThat(rule.isExternal()).isFalse();
+ assertThat(rule.isAdHoc()).isFalse();
+ }
+
+ @Test
public void create_custom_rule_with_empty_parameter_value() {
// insert template rule
RuleDto templateRule = createTemplateRule();
+ NewRuleDescriptionSection defaultSection = new NewRuleDescriptionSection("default", "some description");
NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
.setName("My custom")
- .setHtmlDescription("Some description")
+ .setRuleDescriptionSections(Set.of(defaultSection))
.setSeverity(Severity.MAJOR)
.setStatus(RuleStatus.READY)
.setParameters(ImmutableMap.of("regex", ""));
@@ -153,7 +189,7 @@ public class RuleCreatorTest {
RuleDefinitionDto templateRule = createTemplateRuleWithIntArrayParam();
NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
.setName("My custom")
- .setHtmlDescription("Some description")
+ .setRuleDescriptionSections(Set.of(new NewRuleDescriptionSection("default", "some description")))
.setSeverity(Severity.MAJOR)
.setStatus(RuleStatus.READY);
@@ -174,7 +210,7 @@ public class RuleCreatorTest {
RuleDefinitionDto templateRule = createTemplateRuleWithIntArrayParam();
NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
.setName("My custom")
- .setHtmlDescription("Some description")
+ .setRuleDescriptionSections(Set.of(new NewRuleDescriptionSection("default", "some description")))
.setSeverity(Severity.MAJOR)
.setStatus(RuleStatus.READY)
.setParameters(ImmutableMap.of("myIntegers", "1,3"));
@@ -197,13 +233,13 @@ public class RuleCreatorTest {
NewCustomRule firstRule = NewCustomRule.createForCustomRule("CUSTOM_RULE_1", templateRule.getKey())
.setName("My custom")
- .setHtmlDescription("Some description")
+ .setRuleDescriptionSections(Set.of(new NewRuleDescriptionSection("default", "some description")))
.setSeverity(Severity.MAJOR)
.setStatus(RuleStatus.READY);
NewCustomRule secondRule = NewCustomRule.createForCustomRule("CUSTOM_RULE_2", templateRule.getKey())
.setName("My custom")
- .setHtmlDescription("Some description")
+ .setRuleDescriptionSections(Set.of(new NewRuleDescriptionSection("default", "some description")))
.setSeverity(Severity.MAJOR)
.setStatus(RuleStatus.READY);
@@ -224,16 +260,14 @@ public class RuleCreatorTest {
dbTester.rules().insert(rule);
dbSession.commit();
- assertThatThrownBy(() -> {
- // Create custom rule with unknown template rule
- NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", rule.getKey())
- .setName("My custom")
- .setHtmlDescription("Some description")
- .setSeverity(Severity.MAJOR)
- .setStatus(RuleStatus.READY)
- .setParameters(ImmutableMap.of("regex", "a.*"));
- underTest.create(dbSession, Collections.singletonList(newRule));
- })
+ NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", rule.getKey())
+ .setName("My custom")
+ .setRuleDescriptionSections(Set.of(new NewRuleDescriptionSection("default", "some description")))
+ .setSeverity(Severity.MAJOR)
+ .setStatus(RuleStatus.READY)
+ .setParameters(ImmutableMap.of("regex", "a.*"));
+
+ assertThatThrownBy(() -> underTest.create(dbSession, Collections.singletonList(newRule)))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("This rule is not a template rule: java:S001");
}
@@ -338,7 +372,7 @@ public class RuleCreatorTest {
// Create custom rule with same key, but with different values
NewCustomRule newRule = NewCustomRule.createForCustomRule(key, templateRule.getKey())
.setName("New name")
- .setHtmlDescription("New description")
+ .setRuleDescriptionSections(Set.of(new NewRuleDescriptionSection("default", "some description")))
.setSeverity(Severity.MAJOR)
.setStatus(RuleStatus.READY)
.setParameters(ImmutableMap.of("regex", "c.*"))
@@ -359,15 +393,14 @@ public class RuleCreatorTest {
// insert template rule
RuleDto templateRule = createTemplateRule();
- assertThatThrownBy(() -> {
- NewCustomRule newRule = NewCustomRule.createForCustomRule("*INVALID*", templateRule.getKey())
- .setName("My custom")
- .setHtmlDescription("Some description")
- .setSeverity(Severity.MAJOR)
- .setStatus(RuleStatus.READY)
- .setParameters(ImmutableMap.of("regex", "a.*"));
- underTest.create(dbSession, newRule);
- })
+ NewCustomRule newRule = NewCustomRule.createForCustomRule("*INVALID*", templateRule.getKey())
+ .setName("My custom")
+ .setRuleDescriptionSections(Set.of(new NewRuleDescriptionSection("default", "some description")))
+ .setSeverity(Severity.MAJOR)
+ .setStatus(RuleStatus.READY)
+ .setParameters(ImmutableMap.of("regex", "a.*"));
+
+ assertThatThrownBy(() -> underTest.create(dbSession, newRule))
.isInstanceOf(BadRequestException.class)
.hasMessage("The rule key \"*INVALID*\" is invalid, it should only contain: a-z, 0-9, \"_\"");
}
@@ -379,22 +412,21 @@ public class RuleCreatorTest {
// Create a custom rule
AtomicReference<NewCustomRule> newRule = new AtomicReference<>(NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
.setName("My custom")
- .setHtmlDescription("Some description")
+ .setRuleDescriptionSections(Set.of(new NewRuleDescriptionSection("default", "some description")))
.setSeverity(Severity.MAJOR)
.setStatus(RuleStatus.READY)
.setParameters(ImmutableMap.of("regex", "a.*")));
underTest.create(dbSession, newRule.get());
- assertThatThrownBy(() -> {
- // Create another custom rule having same key
- newRule.set(NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
- .setName("My another custom")
- .setHtmlDescription("Some description")
- .setSeverity(Severity.MAJOR)
- .setStatus(RuleStatus.READY)
- .setParameters(ImmutableMap.of("regex", "a.*")));
- underTest.create(dbSession, newRule.get());
- })
+ // Create another custom rule having same key
+ newRule.set(NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
+ .setName("My another custom")
+ .setRuleDescriptionSections(Set.of(new NewRuleDescriptionSection("default", "some description")))
+ .setSeverity(Severity.MAJOR)
+ .setStatus(RuleStatus.READY)
+ .setParameters(ImmutableMap.of("regex", "a.*")));
+
+ assertThatThrownBy(() -> underTest.create(dbSession, newRule.get()))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("A rule with the key 'CUSTOM_RULE' already exists");
}
@@ -404,14 +436,13 @@ public class RuleCreatorTest {
// insert template rule
RuleDto templateRule = createTemplateRule();
- assertThatThrownBy(() -> {
- NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
- .setHtmlDescription("Some description")
- .setSeverity(Severity.MAJOR)
- .setStatus(RuleStatus.READY)
- .setParameters(ImmutableMap.of("regex", "a.*"));
- underTest.create(dbSession, newRule);
- })
+ NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
+ .setRuleDescriptionSections(Set.of(new NewRuleDescriptionSection("default", "some description")))
+ .setSeverity(Severity.MAJOR)
+ .setStatus(RuleStatus.READY)
+ .setParameters(ImmutableMap.of("regex", "a.*"));
+
+ assertThatThrownBy(() -> underTest.create(dbSession, newRule))
.isInstanceOf(BadRequestException.class)
.hasMessage("The name is missing");
}
@@ -438,14 +469,13 @@ public class RuleCreatorTest {
// insert template rule
RuleDto templateRule = createTemplateRule();
- assertThatThrownBy(() -> {
- NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
- .setName("My custom")
- .setHtmlDescription("Some description")
- .setStatus(RuleStatus.READY)
- .setParameters(ImmutableMap.of("regex", "a.*"));
- underTest.create(dbSession, newRule);
- })
+ NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
+ .setName("My custom")
+ .setRuleDescriptionSections(Set.of(new NewRuleDescriptionSection("default", "some description")))
+ .setStatus(RuleStatus.READY)
+ .setParameters(ImmutableMap.of("regex", "a.*"));
+
+ assertThatThrownBy(() -> underTest.create(dbSession, newRule))
.isInstanceOf(BadRequestException.class)
.hasMessage("The severity is missing");
}
@@ -455,15 +485,14 @@ public class RuleCreatorTest {
// insert template rule
RuleDto templateRule = createTemplateRule();
- assertThatThrownBy(() -> {
- NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
- .setName("My custom")
- .setHtmlDescription("Some description")
- .setSeverity("INVALID")
- .setStatus(RuleStatus.READY)
- .setParameters(ImmutableMap.of("regex", "a.*"));
- underTest.create(dbSession, newRule);
- })
+ NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
+ .setName("My custom")
+ .setRuleDescriptionSections(Set.of(new NewRuleDescriptionSection("default", "some description")))
+ .setSeverity("INVALID")
+ .setStatus(RuleStatus.READY)
+ .setParameters(ImmutableMap.of("regex", "a.*"));
+
+ assertThatThrownBy(() -> underTest.create(dbSession, newRule))
.isInstanceOf(BadRequestException.class)
.hasMessage("Severity \"INVALID\" is invalid");
}
@@ -473,14 +502,13 @@ public class RuleCreatorTest {
// insert template rule
RuleDto templateRule = createTemplateRule();
- assertThatThrownBy(() -> {
- NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
- .setName("My custom")
- .setHtmlDescription("Some description")
- .setSeverity(Severity.MAJOR)
- .setParameters(ImmutableMap.of("regex", "a.*"));
- underTest.create(dbSession, newRule);
- })
+ NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
+ .setName("My custom")
+ .setRuleDescriptionSections(Set.of(new NewRuleDescriptionSection("default", "some description")))
+ .setSeverity(Severity.MAJOR)
+ .setParameters(ImmutableMap.of("regex", "a.*"));
+
+ assertThatThrownBy(() -> underTest.create(dbSession, newRule))
.isInstanceOf(BadRequestException.class)
.hasMessage("The status is missing");
}
@@ -492,16 +520,15 @@ public class RuleCreatorTest {
dbTester.rules().insert(rule);
dbSession.commit();
- assertThatThrownBy(() -> {
- // Create custom rule with unknown template rule
- NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", rule.getKey())
- .setName("My custom")
- .setHtmlDescription("Some description")
- .setSeverity(Severity.MAJOR)
- .setStatus(RuleStatus.READY)
- .setParameters(ImmutableMap.of("regex", "a.*"));
- underTest.create(dbSession, newRule);
- })
+ // Create custom rule with unknown template rule
+ NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", rule.getKey())
+ .setName("My custom")
+ .setRuleDescriptionSections(Set.of(new NewRuleDescriptionSection("default", "some description")))
+ .setSeverity(Severity.MAJOR)
+ .setStatus(RuleStatus.READY)
+ .setParameters(ImmutableMap.of("regex", "a.*"));
+
+ assertThatThrownBy(() -> underTest.create(dbSession, newRule))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("This rule is not a template rule: java:S001");
}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/ListActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/ListActionTest.java
index 9a17510240d..3e6c8eee400 100644
--- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/ListActionTest.java
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/ListActionTest.java
@@ -19,6 +19,7 @@
*/
package org.sonar.server.rule.ws;
+import java.util.Optional;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.rule.RuleKey;
@@ -33,6 +34,9 @@ import static org.assertj.core.api.Assertions.assertThat;
public class ListActionTest {
+ private static final String RULE_KEY_1 = "S001";
+ private static final String RULE_KEY_2 = "S002";
+
@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
@@ -48,8 +52,8 @@ public class ListActionTest {
@Test
public void return_rules_in_protobuf() {
- dbTester.rules().insert(RuleTesting.newRule(RuleKey.of("java", "S001")).setConfigKey(null).setName(null));
- dbTester.rules().insert(RuleTesting.newRule(RuleKey.of("java", "S002")).setConfigKey("I002").setName("Rule Two"));
+ dbTester.rules().insert(RuleTesting.newRule(RuleKey.of("java", RULE_KEY_1)).setConfigKey(null).setName(null));
+ dbTester.rules().insert(RuleTesting.newRule(RuleKey.of("java", RULE_KEY_2)).setConfigKey("I002").setName("Rule Two"));
dbTester.getSession().commit();
Rules.ListResponse listResponse = tester.newRequest()
@@ -57,11 +61,22 @@ public class ListActionTest {
assertThat(listResponse.getRulesCount()).isEqualTo(2);
- assertThat(listResponse.getRules(0).getKey()).isEqualTo("S001");
- assertThat(listResponse.getRules(0).getInternalKey()).isEmpty();
- assertThat(listResponse.getRules(0).getName()).isEmpty();
- assertThat(listResponse.getRules(1).getKey()).isEqualTo("S002");
- assertThat(listResponse.getRules(1).getInternalKey()).isEqualTo("I002");
- assertThat(listResponse.getRules(1).getName()).isEqualTo("Rule Two");
+ Rules.ListResponse.Rule ruleS001 = getRule(listResponse, RULE_KEY_1);
+ assertThat(ruleS001.getKey()).isEqualTo(RULE_KEY_1);
+ assertThat(ruleS001.getInternalKey()).isEmpty();
+ assertThat(ruleS001.getName()).isEmpty();
+
+ Rules.ListResponse.Rule ruleS002 = getRule(listResponse, RULE_KEY_2);
+ assertThat(ruleS002.getKey()).isEqualTo(RULE_KEY_2);
+ assertThat(ruleS002.getInternalKey()).isEqualTo("I002");
+ assertThat(ruleS002.getName()).isEqualTo("Rule Two");
+ }
+
+ private Rules.ListResponse.Rule getRule(Rules.ListResponse listResponse, String ruleKey) {
+ Optional<Rules.ListResponse.Rule> rule = listResponse.getRulesList().stream()
+ .filter(r -> ruleKey.equals(r.getKey()))
+ .findFirst();
+ assertThat(rule).isPresent();
+ return rule.get();
}
}