aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorantoine.vinot <antoine.vinot@sonarsource.com>2024-04-05 11:31:23 +0200
committersonartech <sonartech@sonarsource.com>2024-04-05 20:02:38 +0000
commit118a1b07a78bb95a84defa9535f9999d8f4bd2c5 (patch)
treed98e9956f301aa6b9b446fb3f6dded40e5399add
parent54ad2b1a3d5746ed4702daa1a10845d7b27a0026 (diff)
downloadsonarqube-118a1b07a78bb95a84defa9535f9999d8f4bd2c5.tar.gz
sonarqube-118a1b07a78bb95a84defa9535f9999d8f4bd2c5.zip
SONAR-22009 Fix NPE on SARIF import when Extensions don't have Rules
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/Extension.java2
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/externalissue/sarif/RunMapper.java7
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RunMapperTest.java31
3 files changed, 39 insertions, 1 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Extension.java b/sonar-core/src/main/java/org/sonar/core/sarif/Extension.java
index d3acedeb88f..1e7b16c37bf 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/Extension.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/Extension.java
@@ -21,6 +21,7 @@ package org.sonar.core.sarif;
import com.google.gson.annotations.SerializedName;
import java.util.Set;
+import javax.annotation.CheckForNull;
public class Extension {
@SerializedName("rules")
@@ -33,6 +34,7 @@ public class Extension {
// http://stackoverflow.com/a/18645370/229031
}
+ @CheckForNull
public Set<Rule> getRules() {
return rules;
}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/externalissue/sarif/RunMapper.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/externalissue/sarif/RunMapper.java
index 442e2a1703d..f94549c5ade 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/externalissue/sarif/RunMapper.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/externalissue/sarif/RunMapper.java
@@ -31,6 +31,7 @@ import org.sonar.api.batch.sensor.issue.NewExternalIssue;
import org.sonar.api.batch.sensor.rule.NewAdHocRule;
import org.sonar.api.scanner.ScannerSide;
import org.sonar.core.sarif.Driver;
+import org.sonar.core.sarif.Extension;
import org.sonar.core.sarif.Result;
import org.sonar.core.sarif.Rule;
import org.sonar.core.sarif.Run;
@@ -84,7 +85,7 @@ public class RunMapper {
private List<NewAdHocRule> toNewAdHocRules(Run run, String driverName, Map<String, String> ruleSeveritiesByRuleId, Map<String, String> ruleSeveritiesByRuleIdForNewCCT) {
Set<Rule> driverRules = run.getTool().getDriver().getRules();
Set<Rule> extensionRules = hasExtensions(run.getTool())
- ? run.getTool().getExtensions().stream().flatMap(extension -> extension.getRules().stream()).collect(toSet())
+ ? run.getTool().getExtensions().stream().filter(RunMapper::hasRules).flatMap(extension -> extension.getRules().stream()).collect(toSet())
: Set.of();
return Stream.concat(driverRules.stream(), extensionRules.stream())
.distinct()
@@ -96,6 +97,10 @@ public class RunMapper {
return tool.getExtensions() != null && !tool.getExtensions().isEmpty();
}
+ private static boolean hasRules(Extension extension) {
+ return extension.getRules() != null && !extension.getRules().isEmpty();
+ }
+
private List<NewExternalIssue> toNewExternalIssues(Run run, String driverName, Map<String, String> ruleSeveritiesByRuleId, Map<String, String> ruleSeveritiesByRuleIdForNewCCT) {
return run.getResults()
.stream()
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RunMapperTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RunMapperTest.java
index 67f52b00556..8c03e6cd99a 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RunMapperTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RunMapperTest.java
@@ -42,6 +42,7 @@ import org.sonar.scanner.externalissue.sarif.RunMapper.RunMapperResult;
import static java.util.Collections.emptySet;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
@@ -132,6 +133,36 @@ public class RunMapperTest {
}
@Test
+ public void mapRun_shouldNotFail_whenExtensionsDontHaveRules() {
+ when(run.getTool().getDriver().getRules()).thenReturn(Set.of(rule));
+ Extension extension = mock(Extension.class);
+ when(extension.getRules()).thenReturn(null);
+ when(run.getTool().getExtensions()).thenReturn(Set.of(extension));
+
+ try (MockedStatic<RulesSeverityDetector> detector = mockStatic(RulesSeverityDetector.class)) {
+ detector.when(() -> RulesSeverityDetector.detectRulesSeverities(run, TEST_DRIVER)).thenReturn(Map.of(RULE_ID, WARNING));
+ detector.when(() -> RulesSeverityDetector.detectRulesSeveritiesForNewTaxonomy(run, TEST_DRIVER)).thenReturn(Map.of(RULE_ID, WARNING));
+
+ assertThatNoException().isThrownBy(() -> runMapper.mapRun(run));
+ }
+ }
+
+ @Test
+ public void mapRun_shouldNotFail_whenExtensionsHaveEmptyRules() {
+ when(run.getTool().getDriver().getRules()).thenReturn(Set.of(rule));
+ Extension extension = mock(Extension.class);
+ when(extension.getRules()).thenReturn(Set.of());
+ when(run.getTool().getExtensions()).thenReturn(Set.of(extension));
+
+ try (MockedStatic<RulesSeverityDetector> detector = mockStatic(RulesSeverityDetector.class)) {
+ detector.when(() -> RulesSeverityDetector.detectRulesSeverities(run, TEST_DRIVER)).thenReturn(Map.of(RULE_ID, WARNING));
+ detector.when(() -> RulesSeverityDetector.detectRulesSeveritiesForNewTaxonomy(run, TEST_DRIVER)).thenReturn(Map.of(RULE_ID, WARNING));
+
+ assertThatNoException().isThrownBy(() -> runMapper.mapRun(run));
+ }
+ }
+
+ @Test
public void mapRun_ifRunIsEmpty_returnsEmptyList() {
when(run.getResults()).thenReturn(emptySet());