aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-webserver-webapi
diff options
context:
space:
mode:
authorOrlovAlexander <alexander.orlov@sonarsource.com>2024-10-14 09:03:02 +0200
committersonartech <sonartech@sonarsource.com>2024-10-16 20:03:02 +0000
commitc63283fce767013e11ca6bf1c26170a11c0d48da (patch)
treecd01b86e456639d5149ab9854b4ef65a363a6cf0 /server/sonar-webserver-webapi
parenta49dcbfad564db95c05d538d7aff110a33db12a1 (diff)
downloadsonarqube-c63283fce767013e11ca6bf1c26170a11c0d48da.tar.gz
sonarqube-c63283fce767013e11ca6bf1c26170a11c0d48da.zip
SONAR-23250 Support impacts in QP export-import
Diffstat (limited to 'server/sonar-webserver-webapi')
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileBackuperImplIT.java79
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ImportedRule.java13
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuperImpl.java10
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java43
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileUtils.java46
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/builtin/RuleActivator.java6
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileParserTest.java66
7 files changed, 259 insertions, 4 deletions
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileBackuperImplIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileBackuperImplIT.java
index 71f271bd7ae..286ca058acb 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileBackuperImplIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileBackuperImplIT.java
@@ -27,6 +27,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;
import javax.annotation.Nullable;
@@ -49,8 +50,8 @@ import org.sonar.db.qualityprofile.QProfileDto;
import org.sonar.db.qualityprofile.QualityProfileTesting;
import org.sonar.db.rule.RuleDto;
import org.sonar.db.rule.RuleParamDto;
-import org.sonar.server.qualityprofile.builtin.QProfileName;
import org.sonar.server.common.rule.RuleCreator;
+import org.sonar.server.qualityprofile.builtin.QProfileName;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
@@ -60,6 +61,10 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import static org.sonar.api.issue.impact.Severity.BLOCKER;
+import static org.sonar.api.issue.impact.Severity.INFO;
+import static org.sonar.api.issue.impact.SoftwareQuality.MAINTAINABILITY;
+import static org.sonar.api.issue.impact.SoftwareQuality.SECURITY;
import static org.sonar.db.rule.RuleDescriptionSectionDto.createDefaultRuleDescriptionSection;
import static org.sonar.db.rule.RuleTesting.newRule;
import static org.sonar.db.rule.RuleTesting.newRuleWithoutDescriptionSection;
@@ -101,6 +106,12 @@ class QProfileBackuperImplIT {
"<key>" + rule.getRuleKey() + "</key>" +
"<type>" + RuleType.valueOf(rule.getType()).name() + "</type>" +
"<priority>" + activeRule.getSeverityString() + "</priority>" +
+ "<impacts>" +
+ "<impact>" +
+ "<softwareQuality>MAINTAINABILITY</softwareQuality>" +
+ "<severity>HIGH</severity>" +
+ "</impact>" +
+ "</impacts>" +
"<parameters></parameters>" +
"</rule>" +
"</rules>" +
@@ -125,6 +136,12 @@ class QProfileBackuperImplIT {
"<key>" + rule.getRuleKey() + "</key>" +
"<type>" + RuleType.valueOf(rule.getType()).name() + "</type>" +
"<priority>" + activeRule.getSeverityString() + "</priority>" +
+ "<impacts>" +
+ "<impact>" +
+ "<softwareQuality>MAINTAINABILITY</softwareQuality>" +
+ "<severity>HIGH</severity>" +
+ "</impact>" +
+ "</impacts>" +
"<prioritizedRule>true</prioritizedRule>" +
"<parameters></parameters>" +
"</rule>" +
@@ -148,6 +165,12 @@ class QProfileBackuperImplIT {
"<key>" + rule.getRuleKey() + "</key>" +
"<type>" + RuleType.valueOf(rule.getType()).name() + "</type>" +
"<priority>" + activeRule.getSeverityString() + "</priority>" +
+ "<impacts>" +
+ "<impact>" +
+ "<softwareQuality>MAINTAINABILITY</softwareQuality>" +
+ "<severity>HIGH</severity>" +
+ "</impact>" +
+ "</impacts>" +
"<parameters><parameter>" +
"<key>" + param.getName() + "</key>" +
"<value>20</value>" +
@@ -195,6 +218,12 @@ class QProfileBackuperImplIT {
"<key>" + rule.getKey().rule() + "</key>" +
"<type>" + RuleType.valueOf(rule.getType()) + "</type>" +
"<priority>" + activeRule.getSeverityString() + "</priority>" +
+ "<impacts>" +
+ "<impact>" +
+ "<softwareQuality>MAINTAINABILITY</softwareQuality>" +
+ "<severity>HIGH</severity>" +
+ "</impact>" +
+ "</impacts>" +
"<name>" + rule.getName() + "</name>" +
"<templateKey>" + templateRule.getKey().rule() + "</templateKey>" +
"<description>" + rule.getDefaultRuleDescriptionSection().getContent() + "</description>" +
@@ -225,6 +254,12 @@ class QProfileBackuperImplIT {
"<key>" + rule.getKey().rule() + "</key>" +
"<type>" + RuleType.valueOf(rule.getType()) + "</type>" +
"<priority>" + activeRule.getSeverityString() + "</priority>" +
+ "<impacts>" +
+ "<impact>" +
+ "<softwareQuality>MAINTAINABILITY</softwareQuality>" +
+ "<severity>HIGH</severity>" +
+ "</impact>" +
+ "</impacts>" +
"<parameters><parameter>" +
"<key>" + param.getName() + "</key>" +
"<value>20</value>" +
@@ -459,6 +494,48 @@ class QProfileBackuperImplIT {
}
@Test
+ void restore_should_override_impacts(){
+ String ruleUuid = db.rules().insert(RuleKey.of("sonarjs", "s001")).getUuid();
+
+ Reader backup = new StringReader("<?xml version='1.0' encoding='UTF-8'?>" +
+ "<profile><name>foo</name>" +
+ "<language>js</language>" +
+ "<rules>" +
+ "<rule>" +
+ "<repositoryKey>sonarjs</repositoryKey>" +
+ "<key>s001</key>" +
+ "<priority>BLOCKER</priority>" +
+ "<impacts>" +
+ "<impact>" +
+ "<softwareQuality>MAINTAINABILITY</softwareQuality>" +
+ "<severity>BLOCKER</severity>" +
+ "</impact>" +
+ "<impact>" +
+ "<softwareQuality>SECURITY</softwareQuality>" +
+ "<severity>INFO</severity>" +
+ "</impact>" +
+ "</impacts>" +
+ "<parameters>" +
+ "<parameter><key>bar</key><value>baz</value></parameter>" +
+ "</parameters>" +
+ "</rule>" +
+ "</rules>" +
+ "</profile>");
+
+ underTest.restore(db.getSession(), backup, (String) null);
+
+ assertThat(reset.calledActivations).hasSize(1);
+ RuleActivation activation = reset.calledActivations.get(0);
+ assertThat(activation.getSeverity()).isEqualTo("BLOCKER");
+ assertThat(activation.getRuleUuid()).isEqualTo(ruleUuid);
+ assertThat(activation.getImpactSeverities()).isEqualTo(Map.of(MAINTAINABILITY, BLOCKER, SECURITY, INFO));
+ db.getDbClient().activeRuleDao().selectByRuleUuid(db.getSession(), ruleUuid).forEach(ar -> {
+ assertThat(ar.getSeverityString()).isEqualTo("BLOCKER");
+ assertThat(ar.getImpactsString()).isEqualTo("{\"MAINTAINABILITY\":\"BLOCKER\",\"SECURITY\":\"INFO\"}");
+ });
+ }
+
+ @Test
void copy_profile() {
RuleDto rule = createRule();
RuleParamDto param = db.rules().insertRuleParam(rule);
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 410fe724eaf..544a41022a4 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
@@ -20,7 +20,7 @@
package org.sonar.server.qualityprofile;
import java.util.Map;
-
+import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.api.rule.RuleKey;
class ImportedRule {
@@ -32,9 +32,11 @@ class ImportedRule {
private String name = null;
private String type = null;
private String severity = null;
+ private Map<SoftwareQuality, org.sonar.api.issue.impact.Severity> impacts = Map.of();
private Boolean prioritizedRule = false;
private String description = null;
private Map<String, String> parameters = null;
+
public Map<String, String> getParameters() {
return parameters;
}
@@ -59,6 +61,10 @@ class ImportedRule {
return severity;
}
+ public Map<SoftwareQuality, org.sonar.api.issue.impact.Severity> getImpacts() {
+ return impacts;
+ }
+
public Boolean getPrioritizedRule() {
return prioritizedRule;
}
@@ -77,6 +83,11 @@ class ImportedRule {
return this;
}
+ ImportedRule setImpacts(Map<SoftwareQuality, org.sonar.api.issue.impact.Severity> impacts) {
+ this.impacts = impacts;
+ return this;
+ }
+
public ImportedRule setPrioritizedRule(Boolean prioritizedRule) {
this.prioritizedRule = prioritizedRule;
return this;
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 4c709b0a285..e6f8b9b78e4 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
@@ -50,6 +50,7 @@ import org.sonar.server.qualityprofile.builtin.QProfileName;
import static com.google.common.base.Preconditions.checkArgument;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toSet;
+import static org.sonar.server.qualityprofile.QProfileUtils.parseImpactsToMap;
@ServerSide
public class QProfileBackuperImpl implements QProfileBackuper {
@@ -95,6 +96,7 @@ public class QProfileBackuperImpl implements QProfileBackuper {
importedRule.setRepository(ruleKey.repository());
importedRule.setKey(ruleKey.rule());
importedRule.setSeverity(exportRuleDto.getSeverityString());
+ importedRule.setImpacts(exportRuleDto.getImpacts() != null ? parseImpactsToMap(exportRuleDto.getImpacts()) : Map.of());
if (exportRuleDto.isCustomRule()) {
importedRule.setTemplate(exportRuleDto.getTemplateRuleKey().rule());
importedRule.setDescription(exportRuleDto.getDescriptionOrThrow());
@@ -213,6 +215,7 @@ public class QProfileBackuperImpl implements QProfileBackuper {
return NewCustomRule.createForCustomRule(r.getRuleKey(), r.getTemplateKey())
.setName(r.getName())
.setSeverity(r.getSeverity())
+ .setImpacts(r.getImpacts().entrySet().stream().map(i -> new NewCustomRule.Impact(i.getKey(), i.getValue())).toList())
.setStatus(RuleStatus.READY)
.setPreventReactivation(true)
.setType(RuleType.valueOf(r.getType()))
@@ -228,7 +231,12 @@ public class QProfileBackuperImpl implements QProfileBackuper {
if (ruleDto == null) {
continue;
}
- activatedRule.add(RuleActivation.create(ruleDto.getUuid(), r.getSeverity(), r.getPrioritizedRule(), r.getParameters()));
+ activatedRule.add(RuleActivation.create(
+ ruleDto.getUuid(),
+ r.getSeverity(),
+ r.getImpacts(),
+ r.getPrioritizedRule(),
+ r.getParameters()));
}
return activatedRule;
}
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 f0c1d16411a..e29e02bf6ca 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
@@ -22,6 +22,7 @@ package org.sonar.server.qualityprofile;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
+import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -36,6 +37,8 @@ import org.apache.commons.lang3.StringUtils;
import org.codehaus.staxmate.SMInputFactory;
import org.codehaus.staxmate.in.SMHierarchicCursor;
import org.codehaus.staxmate.in.SMInputCursor;
+import org.sonar.api.issue.impact.Severity;
+import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.text.XmlWriter;
@@ -43,6 +46,8 @@ import org.sonar.db.qualityprofile.ExportRuleDto;
import org.sonar.db.qualityprofile.ExportRuleParamDto;
import org.sonar.db.qualityprofile.QProfileDto;
+import static org.sonar.server.qualityprofile.QProfileUtils.parseImpactsToMap;
+
@ServerSide
public class QProfileParser {
private static final String ATTRIBUTE_PROFILE = "profile";
@@ -53,6 +58,10 @@ public class QProfileParser {
private static final String ATTRIBUTE_REPOSITORY_KEY = "repositoryKey";
private static final String ATTRIBUTE_KEY = "key";
private static final String ATTRIBUTE_PRIORITY = "priority";
+ private static final String ATTRIBUTE_IMPACTS = "impacts";
+ private static final String ATTRIBUTE_IMPACT = "impact";
+ private static final String ATTRIBUTE_SEVERITY = "severity";
+ private static final String ATTRIBUTE_SOFTWARE_QUALITY = "softwareQuality";
private static final String ATTRIBUTE_PRIORITIZED_RULE = "prioritizedRule";
private static final String ATTRIBUTE_TEMPLATE_KEY = "templateKey";
private static final String ATTRIBUTE_TYPE = "type";
@@ -76,6 +85,16 @@ public class QProfileParser {
xml.prop(ATTRIBUTE_KEY, ruleToExport.getRuleKey().rule());
xml.prop(ATTRIBUTE_TYPE, ruleToExport.getRuleType().name());
xml.prop(ATTRIBUTE_PRIORITY, ruleToExport.getSeverityString());
+ if (StringUtils.isNotEmpty(ruleToExport.getImpacts())) {
+ xml.begin(ATTRIBUTE_IMPACTS);
+ parseImpactsToMap(ruleToExport.getImpacts()).forEach((quality, severity) -> {
+ xml.begin(ATTRIBUTE_IMPACT);
+ xml.prop(ATTRIBUTE_SOFTWARE_QUALITY, quality.name());
+ xml.prop(ATTRIBUTE_SEVERITY, severity.name());
+ xml.end();
+ });
+ xml.end();
+ }
if (Boolean.TRUE.equals(ruleToExport.getPrioritizedRule())) {
xml.prop(ATTRIBUTE_PRIORITIZED_RULE, ruleToExport.getPrioritizedRule());
}
@@ -181,6 +200,11 @@ public class QProfileParser {
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_IMPACTS, nodeName)) {
+ SMInputCursor impactsCursor = ruleCursor.childElementCursor(ATTRIBUTE_IMPACT);
+ Map<SoftwareQuality, Severity> impacts = new EnumMap<>(SoftwareQuality.class);
+ readImpacts(impactsCursor, impacts);
+ rule.setImpacts(impacts);
} else if (StringUtils.equals(ATTRIBUTE_PRIORITIZED_RULE, nodeName)) {
rule.setPrioritizedRule(Boolean.valueOf(StringUtils.trim(ruleCursor.collectDescendantText(false))));
} else if (StringUtils.equals(ATTRIBUTE_PARAMETERS, nodeName)) {
@@ -209,4 +233,23 @@ public class QProfileParser {
}
}
}
+
+ private static void readImpacts(SMInputCursor impactsCursor, Map<SoftwareQuality, Severity> impacts) throws XMLStreamException {
+ while (impactsCursor.getNext() != null) {
+ SMInputCursor impactCursor = impactsCursor.childElementCursor();
+ SoftwareQuality softwareQuality = null;
+ Severity severity = null;
+ while (impactCursor.getNext() != null) {
+ String nodeName = impactCursor.getLocalName();
+ if (StringUtils.equals(ATTRIBUTE_SOFTWARE_QUALITY, nodeName)) {
+ softwareQuality = SoftwareQuality.valueOf(StringUtils.trim(impactCursor.collectDescendantText(false)));
+ } else if (StringUtils.equals(ATTRIBUTE_SEVERITY, nodeName)) {
+ severity = Severity.valueOf(StringUtils.trim(impactCursor.collectDescendantText(false)));
+ }
+ }
+ if (softwareQuality != null && severity != null) {
+ impacts.put(softwareQuality, severity);
+ }
+ }
+ }
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileUtils.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileUtils.java
new file mode 100644
index 00000000000..a78bc0cc9bc
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileUtils.java
@@ -0,0 +1,46 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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 com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.EnumMap;
+import java.util.Map;
+import org.sonar.api.issue.impact.Severity;
+import org.sonar.api.issue.impact.SoftwareQuality;
+
+public class QProfileUtils {
+
+ private QProfileUtils() {
+ }
+
+ public static Map<SoftwareQuality, Severity> parseImpactsToMap(String impacts) {
+ ObjectMapper mapper = new ObjectMapper();
+ Map<SoftwareQuality, Severity> parsedMap = new EnumMap<>(SoftwareQuality.class);
+ try {
+ Map<String, String> stringMap = mapper.readValue(impacts, Map.class);
+ for (Map.Entry<String, String> entry : stringMap.entrySet()) {
+ parsedMap.put(SoftwareQuality.valueOf(entry.getKey()), Severity.valueOf(entry.getValue()));
+ }
+ } catch (Exception e) {
+ throw new IllegalArgumentException("The quality profile cannot be restored as it contains invalid impacts: " + impacts);
+ }
+ return parsedMap;
+ }
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/builtin/RuleActivator.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/builtin/RuleActivator.java
index 98d6bf350b9..146b0d5c69c 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/builtin/RuleActivator.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/builtin/RuleActivator.java
@@ -259,11 +259,15 @@ public class RuleActivator {
@Nullable ActiveRuleWrapper parentActiveRule) {
String requestSeverity = request.getSeverity();
if (requestSeverity != null) {
+ Map<SoftwareQuality, Severity> impactSeverities = request.getImpactSeverities();
+ if (impactSeverities != null && !impactSeverities.isEmpty()) {
+ return new SeverityConfiguration(requestSeverity, impactSeverities);
+ }
// When standard severity is requested to be overridden, we translate it to the impact to override
return new SeverityConfiguration(requestSeverity,
QProfileImpactSeverityMapper.mapImpactSeverities(requestSeverity, ruleDto.getDefaultImpactsMap(), ruleDto.getEnumType()));
} else if (!request.getImpactSeverities().isEmpty()) {
- // If an impact is request to be overridden, we translat it to the standard severity
+ // If an impact is request to be overridden, we translate it to the standard severity
return new SeverityConfiguration(
QProfileImpactSeverityMapper.mapSeverity(request.getImpactSeverities(), ruleDto.getEnumType(), ruleDto.getSeverityString()),
request.getImpactSeverities());
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
index 084bed6dad2..accbcfa7e12 100644
--- 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
@@ -21,9 +21,15 @@ package org.sonar.server.qualityprofile;
import java.io.Reader;
import java.io.StringReader;
+import java.util.Map;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
+import static org.sonar.api.issue.impact.Severity.BLOCKER;
+import static org.sonar.api.issue.impact.Severity.INFO;
+import static org.sonar.api.issue.impact.SoftwareQuality.MAINTAINABILITY;
+import static org.sonar.api.issue.impact.SoftwareQuality.SECURITY;
class QProfileParserTest {
@@ -40,6 +46,16 @@ class QProfileParserTest {
<key>s001</key>
<type>CODE_SMELL</type>
<priority>CRITICAL</priority>
+ <impacts>
+ <impact>
+ <softwareQuality>MAINTAINABILITY</softwareQuality>
+ <severity>BLOCKER</severity>
+ </impact>
+ <impact>
+ <softwareQuality>SECURITY</softwareQuality>
+ <severity>INFO</severity>
+ </impact>
+ </impacts>
<name>custom rule name</name>
<templateKey>rule_mc8</templateKey>
<description>custom rule description</description>
@@ -72,6 +88,7 @@ class QProfileParserTest {
<type>CODE_SMELL</type>
<priority>CRITICAL</priority>
<prioritizedRule>false</prioritizedRule>
+ <impacts></impacts>
<name>custom rule name</name>
<templateKey>rule_mc8</templateKey>
<description>custom rule description</description>
@@ -90,9 +107,58 @@ class QProfileParserTest {
var importedRule = importedQProfile.getRules().get(0);
assertThat(importedRule.getDescription()).isEqualTo("custom rule description");
assertThat(importedRule.getPrioritizedRule()).isFalse();
+ assertThat(importedRule.getImpacts()).isEqualTo(Map.of(MAINTAINABILITY, BLOCKER, SECURITY, INFO));
importedRule = importedQProfile.getRules().get(1);
assertThat(importedRule.getPrioritizedRule()).isTrue();
+ assertThat(importedRule.getImpacts()).isEmpty();
importedRule = importedQProfile.getRules().get(2);
assertThat(importedRule.getPrioritizedRule()).isFalse();
+ assertThat(importedRule.getImpacts()).isEmpty();
+ }
+
+ @Test
+ //test that exception is thrown if impacts has incorrect arguments
+ void readXml_whenImpactsIncorrectArguments_shouldThrow() {
+ 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>
+ <impacts>
+ <impact>
+ <softwareQuality>MAINTAINABILITY</softwareQuality>
+ <severity>BLOCKER</severity>
+ </impact>
+ <impact>
+ <softwareQuality>SECURITY</softwareQuality>
+ <severity>INFO</severity>
+ </impact>
+ <impact>
+ <softwareQuality>RELIABILITY</softwareQuality>
+ <severity>MAJOR</severity>
+ <impact>
+ </impacts>
+ <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();
+ assertThatThrownBy(() -> parser.readXml(backup))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("No enum constant org.sonar.api.issue.impact.Severity.MAJOR");
}
}