]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-19522 Fail-fast if SARIF file doesn't exist. (#8587)
authorWojtek Wajerowicz <115081248+wojciech-wajerowicz-sonarsource@users.noreply.github.com>
Thu, 15 Jun 2023 15:04:02 +0000 (17:04 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 15 Jun 2023 20:03:02 +0000 (20:03 +0000)
sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializer.java
sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializerImpl.java
sonar-core/src/test/java/org/sonar/core/sarif/SarifSerializerImplTest.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/sarif/SarifSerializerTest.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/externalissue/sarif/SarifIssuesImportSensor.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/SarifIssuesImportSensorTest.java

index fb9777a6bbc1b3808d25fad07d13a0666b9c71b9..a20b18f280a572c0cf2fec2af9788baddd30fc76 100644 (file)
  */
 package org.sonar.core.sarif;
 
+import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
 
 public interface SarifSerializer {
 
   String serialize(Sarif210 sarif210);
 
-  Sarif210 deserialize(Path sarifPath);
+  Sarif210 deserialize(Path sarifPath) throws NoSuchFileException;
 }
index 487f81cf10aebf63b45fffbad0e36f5ea64af6e5..202dd59bad4122ff75e15da63ce819b056469f83 100644 (file)
@@ -25,6 +25,7 @@ import com.google.gson.JsonIOException;
 import com.google.gson.JsonSyntaxException;
 import java.io.IOException;
 import java.io.Reader;
+import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
 import javax.inject.Inject;
 import org.sonar.api.ce.ComputeEngineSide;
@@ -58,17 +59,17 @@ public class SarifSerializerImpl implements SarifSerializer {
   }
 
   @Override
-  public Sarif210 deserialize(Path reportPath) {
+  public Sarif210 deserialize(Path reportPath) throws NoSuchFileException {
     try (Reader reader = newBufferedReader(reportPath, UTF_8)) {
       Sarif210 sarif = gson.fromJson(reader, Sarif210.class);
       SarifVersionValidator.validateSarifVersion(sarif.getVersion());
       return sarif;
+    } catch (NoSuchFileException e) {
+      throw e;
     } catch (JsonIOException | IOException e) {
       throw new IllegalStateException(format(SARIF_REPORT_ERROR, reportPath), e);
     } catch (JsonSyntaxException e) {
       throw new IllegalStateException(format(SARIF_JSON_SYNTAX_ERROR, reportPath), e);
-    } catch (IllegalStateException e) {
-      throw new IllegalStateException(e.getMessage(), e);
     }
   }
 }
diff --git a/sonar-core/src/test/java/org/sonar/core/sarif/SarifSerializerImplTest.java b/sonar-core/src/test/java/org/sonar/core/sarif/SarifSerializerImplTest.java
new file mode 100644 (file)
index 0000000..3a240cf
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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.core.sarif;
+
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import static java.lang.String.format;
+import static java.util.Objects.requireNonNull;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.Assertions.fail;
+import static org.sonar.core.sarif.SarifVersionValidator.UNSUPPORTED_VERSION_MESSAGE_TEMPLATE;
+
+@RunWith(MockitoJUnitRunner.class)
+public class SarifSerializerImplTest {
+
+  private static final String SARIF_JSON = "{\"version\":\"2.1.0\",\"$schema\":\"http://json.schemastore.org/sarif-2.1.0-rtm.4\",\"runs\":[{\"results\":[]}]}";
+
+  private final SarifSerializerImpl serializer = new SarifSerializerImpl();
+
+  @Test
+  public void serialize() {
+    Run.builder().results(Set.of()).build();
+    Sarif210 sarif210 = new Sarif210("http://json.schemastore.org/sarif-2.1.0-rtm.4", Run.builder().results(Set.of()).build());
+
+    String result = serializer.serialize(sarif210);
+
+    assertThat(result).isEqualTo(SARIF_JSON);
+  }
+
+  @Test
+  public void deserialize() throws URISyntaxException, NoSuchFileException {
+    URL sarifResource = requireNonNull(getClass().getResource("eslint-sarif210.json"));
+    Path sarif = Paths.get(sarifResource.toURI());
+
+    Sarif210 deserializationResult = serializer.deserialize(sarif);
+
+    verifySarif(deserializationResult);
+  }
+
+  @Test
+  public void deserialize_shouldFail_whenFileCantBeFound() {
+    String file = "wrongPathToFile";
+    Path sarif = Paths.get(file);
+
+    assertThatThrownBy(() -> serializer.deserialize(sarif))
+      .isInstanceOf(NoSuchFileException.class);
+  }
+
+  @Test
+  public void deserialize_shouldFail_whenJsonSyntaxIsIncorrect() throws URISyntaxException {
+    URL sarifResource = requireNonNull(getClass().getResource("invalid-json-syntax.json"));
+    Path sarif = Paths.get(sarifResource.toURI());
+
+    assertThatThrownBy(() -> serializer.deserialize(sarif))
+      .isInstanceOf(IllegalStateException.class)
+      .hasMessage(format("Failed to read SARIF report at '%s': invalid JSON syntax or file is not UTF-8 encoded", sarif));
+  }
+
+  @Test
+  public void deserialize_whenFileIsNotUtf8encoded_shouldFail() throws URISyntaxException {
+    URL sarifResource = requireNonNull(getClass().getResource("sarif210-nonUtf8.json"));
+    Path sarif = Paths.get(sarifResource.toURI());
+
+    assertThatThrownBy(() -> serializer.deserialize(sarif))
+      .isInstanceOf(IllegalStateException.class)
+      .hasMessage(format("Failed to read SARIF report at '%s': invalid JSON syntax or file is not UTF-8 encoded", sarif));
+  }
+
+  @Test
+  public void deserialize_shouldFail_whenSarifVersionIsNotSupported() throws URISyntaxException {
+    URL sarifResource = requireNonNull(getClass().getResource("unsupported-sarif-version-abc.json"));
+    Path sarif = Paths.get(sarifResource.toURI());
+
+    assertThatThrownBy(() -> serializer.deserialize(sarif))
+      .isInstanceOf(IllegalStateException.class)
+      .hasMessage(format(UNSUPPORTED_VERSION_MESSAGE_TEMPLATE, "A.B.C"));
+  }
+
+  private void verifySarif(Sarif210 deserializationResult) {
+    Sarif210 expected = buildExpectedSarif210();
+
+    assertThat(deserializationResult).isNotNull();
+    assertThat(deserializationResult).usingRecursiveComparison().ignoringFields("runs").isEqualTo(expected);
+
+    Run run = getRun(deserializationResult);
+    Run expectedRun = getRun(expected);
+    assertThat(run).usingRecursiveComparison().ignoringFields("results", "tool.driver.rules").isEqualTo(expectedRun);
+
+    Result result = getResult(run);
+    Result expectedResult = getResult(expectedRun);
+    assertThat(result).usingRecursiveComparison().isEqualTo(expectedResult);
+
+    Rule rule = getRule(run);
+    Rule expectedRule = getRule(expectedRun);
+    assertThat(rule).usingRecursiveComparison().ignoringFields("properties").isEqualTo(expectedRule);
+  }
+
+  private static Sarif210 buildExpectedSarif210() {
+    return new Sarif210("http://json.schemastore.org/sarif-2.1.0-rtm.4", buildExpectedRun());
+  }
+
+  private static Run buildExpectedRun() {
+    Tool tool = new Tool(buildExpectedDriver());
+    return Run.builder()
+      .tool(tool)
+      .results(Set.of(buildExpectedResult())).build();
+  }
+
+  private static Driver buildExpectedDriver() {
+    return Driver.builder()
+      .name("ESLint")
+      .rules(Set.of(buildExpectedRule()))
+      .build();
+  }
+
+  private static Rule buildExpectedRule() {
+    return Rule.builder()
+      .id("no-unused-vars")
+      .shortDescription("disallow unused variables")
+      .build();
+  }
+
+  private static Result buildExpectedResult() {
+    return Result.builder()
+      .ruleId("no-unused-vars")
+      .locations(Set.of(buildExpectedLocation()))
+      .message("'x' is assigned a value but never used.")
+      .level("error")
+      .build();
+  }
+
+  private static Location buildExpectedLocation() {
+    ArtifactLocation artifactLocation = new ArtifactLocation(null, "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js");
+    PhysicalLocation physicalLocation = PhysicalLocation.of(artifactLocation, buildExpectedRegion());
+    return Location.of(physicalLocation);
+  }
+
+  private static Region buildExpectedRegion() {
+    return Region.builder()
+      .startLine(1)
+      .startColumn(5)
+      .build();
+  }
+
+  private static Run getRun(Sarif210 sarif210) {
+    return sarif210.getRuns().stream().findFirst().orElseGet(() -> fail("runs property is missing"));
+  }
+
+  private static Result getResult(Run run) {
+    return run.getResults().stream().findFirst().orElseGet(() -> fail("results property is missing"));
+  }
+
+  private static Rule getRule(Run run) {
+    return run.getTool().getDriver().getRules().stream().findFirst().orElseGet(() -> fail("rules property is missing"));
+  }
+
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/sarif/SarifSerializerTest.java b/sonar-core/src/test/java/org/sonar/core/sarif/SarifSerializerTest.java
deleted file mode 100644 (file)
index 2453226..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 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.core.sarif;
-
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Set;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.junit.MockitoJUnitRunner;
-
-import static java.lang.String.format;
-import static java.util.Objects.requireNonNull;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.assertj.core.api.Assertions.fail;
-import static org.sonar.core.sarif.SarifVersionValidator.UNSUPPORTED_VERSION_MESSAGE_TEMPLATE;
-
-@RunWith(MockitoJUnitRunner.class)
-public class SarifSerializerTest {
-
-  private static final String SARIF_JSON = "{\"version\":\"2.1.0\",\"$schema\":\"http://json.schemastore.org/sarif-2.1.0-rtm.4\",\"runs\":[{\"results\":[]}]}";
-
-  private final SarifSerializerImpl serializer = new SarifSerializerImpl();
-
-  @Test
-  public void serialize() {
-    Run.builder().results(Set.of()).build();
-    Sarif210 sarif210 = new Sarif210("http://json.schemastore.org/sarif-2.1.0-rtm.4", Run.builder().results(Set.of()).build());
-
-    String result = serializer.serialize(sarif210);
-
-    assertThat(result).isEqualTo(SARIF_JSON);
-  }
-
-  @Test
-  public void deserialize() throws URISyntaxException {
-    URL sarifResource = requireNonNull(getClass().getResource("eslint-sarif210.json"));
-    Path sarif = Paths.get(sarifResource.toURI());
-
-    Sarif210 deserializationResult = serializer.deserialize(sarif);
-
-    verifySarif(deserializationResult);
-  }
-
-  @Test
-  public void deserialize_shouldFail_whenFileCantBeFound() {
-    String file = "wrongPathToFile";
-    Path sarif = Paths.get(file);
-
-    assertThatThrownBy(() -> serializer.deserialize(sarif))
-      .isInstanceOf(IllegalStateException.class)
-      .hasMessage(format("Failed to read SARIF report at '%s'", file));
-  }
-
-  @Test
-  public void deserialize_shouldFail_whenJsonSyntaxIsIncorrect() throws URISyntaxException {
-    URL sarifResource = requireNonNull(getClass().getResource("invalid-json-syntax.json"));
-    Path sarif = Paths.get(sarifResource.toURI());
-
-    assertThatThrownBy(() -> serializer.deserialize(sarif))
-      .isInstanceOf(IllegalStateException.class)
-      .hasMessage(format("Failed to read SARIF report at '%s': invalid JSON syntax or file is not UTF-8 encoded", sarif));
-  }
-
-  @Test
-  public void deserialize_whenFileIsNotUtf8encoded_shouldFail() throws URISyntaxException {
-    URL sarifResource = requireNonNull(getClass().getResource("sarif210-nonUtf8.json"));
-    Path sarif = Paths.get(sarifResource.toURI());
-
-    assertThatThrownBy(() -> serializer.deserialize(sarif))
-      .isInstanceOf(IllegalStateException.class)
-      .hasMessage(format("Failed to read SARIF report at '%s': invalid JSON syntax or file is not UTF-8 encoded", sarif));
-  }
-
-  @Test
-  public void deserialize_shouldFail_whenSarifVersionIsNotSupported() throws URISyntaxException {
-    URL sarifResource = requireNonNull(getClass().getResource("unsupported-sarif-version-abc.json"));
-    Path sarif = Paths.get(sarifResource.toURI());
-
-    assertThatThrownBy(() -> serializer.deserialize(sarif))
-      .isInstanceOf(IllegalStateException.class)
-      .hasMessage(format(UNSUPPORTED_VERSION_MESSAGE_TEMPLATE, "A.B.C"));
-  }
-
-  private void verifySarif(Sarif210 deserializationResult) {
-    Sarif210 expected = buildExpectedSarif210();
-
-    assertThat(deserializationResult).isNotNull();
-    assertThat(deserializationResult).usingRecursiveComparison().ignoringFields("runs").isEqualTo(expected);
-
-    Run run = getRun(deserializationResult);
-    Run expectedRun = getRun(expected);
-    assertThat(run).usingRecursiveComparison().ignoringFields("results", "tool.driver.rules").isEqualTo(expectedRun);
-
-    Result result = getResult(run);
-    Result expectedResult = getResult(expectedRun);
-    assertThat(result).usingRecursiveComparison().isEqualTo(expectedResult);
-
-    Rule rule = getRule(run);
-    Rule expectedRule = getRule(expectedRun);
-    assertThat(rule).usingRecursiveComparison().ignoringFields("properties").isEqualTo(expectedRule);
-  }
-
-  private static Sarif210 buildExpectedSarif210() {
-    return new Sarif210("http://json.schemastore.org/sarif-2.1.0-rtm.4", buildExpectedRun());
-  }
-
-  private static Run buildExpectedRun() {
-    Tool tool = new Tool(buildExpectedDriver());
-    return Run.builder()
-      .tool(tool)
-      .results(Set.of(buildExpectedResult())).build();
-  }
-
-  private static Driver buildExpectedDriver() {
-    return Driver.builder()
-      .name("ESLint")
-      .rules(Set.of(buildExpectedRule()))
-      .build();
-  }
-
-  private static Rule buildExpectedRule() {
-    return Rule.builder()
-      .id("no-unused-vars")
-      .shortDescription("disallow unused variables")
-      .build();
-  }
-
-  private static Result buildExpectedResult() {
-    return Result.builder()
-      .ruleId("no-unused-vars")
-      .locations(Set.of(buildExpectedLocation()))
-      .message("'x' is assigned a value but never used.")
-      .level("error")
-      .build();
-  }
-
-  private static Location buildExpectedLocation() {
-    ArtifactLocation artifactLocation = new ArtifactLocation(null, "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js");
-    PhysicalLocation physicalLocation = PhysicalLocation.of(artifactLocation, buildExpectedRegion());
-    return Location.of(physicalLocation);
-  }
-
-  private static Region buildExpectedRegion() {
-    return Region.builder()
-      .startLine(1)
-      .startColumn(5)
-      .build();
-  }
-
-  private static Run getRun(Sarif210 sarif210) {
-    return sarif210.getRuns().stream().findFirst().orElseGet(() -> fail("runs property is missing"));
-  }
-
-  private static Result getResult(Run run) {
-    return run.getResults().stream().findFirst().orElseGet(() -> fail("results property is missing"));
-  }
-
-  private static Rule getRule(Run run) {
-    return run.getTool().getDriver().getRules().stream().findFirst().orElseGet(() -> fail("rules property is missing"));
-  }
-
-}
index 346cb727f7db6187c64b5151d5c321a725a8a7c9..53a2a651ddeba7d83a80e8d4d500bbf8e1e1318f 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.scanner.externalissue.sarif;
 
+import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.Collections;
@@ -37,9 +38,12 @@ import org.sonar.api.config.PropertyDefinition;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.scanner.ScannerSide;
 import org.sonar.api.scanner.sensor.ProjectSensor;
+import org.sonar.api.utils.MessageException;
 import org.sonar.core.sarif.Sarif210;
 import org.sonar.core.sarif.SarifSerializer;
 
+import static java.lang.String.format;
+
 @ScannerSide
 public class SarifIssuesImportSensor implements ProjectSensor {
 
@@ -81,6 +85,8 @@ public class SarifIssuesImportSensor implements ProjectSensor {
       try {
         SarifImportResults sarifImportResults = processReport(context, reportPath);
         filePathToImportResults.put(reportPath, sarifImportResults);
+      } catch (NoSuchFileException e) {
+        throw MessageException.of(format("SARIF report file not found: %s", e.getFile()));
       } catch (Exception exception) {
         LOG.warn("Failed to process SARIF report from file '{}', error: '{}'", reportPath, exception.getMessage());
       }
@@ -92,7 +98,7 @@ public class SarifIssuesImportSensor implements ProjectSensor {
     return Arrays.stream(config.getStringArray(SARIF_REPORT_PATHS_PROPERTY_KEY)).collect(Collectors.toSet());
   }
 
-  private SarifImportResults processReport(SensorContext context, String reportPath) {
+  private SarifImportResults processReport(SensorContext context, String reportPath) throws NoSuchFileException {
     LOG.debug("Importing SARIF issues from '{}'", reportPath);
     Path reportFilePath = context.fileSystem().resolvePath(reportPath).toPath();
     Sarif210 sarifReport = sarifSerializer.deserialize(reportFilePath);
index 6a85b604a86d1a427393a6ccb7d0d6b4a492f841..f3181825034db4b148535500ee997781a178255d 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.scanner.externalissue.sarif;
 
 import com.google.common.collect.MoreCollectors;
+import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
 import java.util.Optional;
 import org.junit.Before;
@@ -33,11 +34,13 @@ import org.sonar.api.batch.sensor.internal.SensorContextTester;
 import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.testfixtures.log.LogAndArguments;
 import org.sonar.api.testfixtures.log.LogTester;
+import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.core.sarif.Sarif210;
 import org.sonar.core.sarif.SarifSerializer;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -68,7 +71,7 @@ public class SarifIssuesImportSensorTest {
   private final SensorContextTester sensorContext = SensorContextTester.create(Path.of("."));
 
   @Test
-  public void execute_whenSingleFileIsSpecified_shouldImportResults() {
+  public void execute_whenSingleFileIsSpecified_shouldImportResults() throws NoSuchFileException {
     sensorSettings.setProperty("sonar.sarifReportPaths", FILE_1);
 
     ReportAndResults reportAndResults = mockSuccessfulReportAndResults(FILE_1);
@@ -83,7 +86,7 @@ public class SarifIssuesImportSensorTest {
   }
 
   @Test
-  public void execute_whenMultipleFilesAreSpecified_shouldImportResults() {
+  public void execute_whenMultipleFilesAreSpecified_shouldImportResults() throws NoSuchFileException {
     sensorSettings.setProperty("sonar.sarifReportPaths", SARIF_REPORT_PATHS_PARAM);
     ReportAndResults reportAndResults1 = mockSuccessfulReportAndResults(FILE_1);
     ReportAndResults reportAndResults2 = mockSuccessfulReportAndResults(FILE_2);
@@ -99,7 +102,7 @@ public class SarifIssuesImportSensorTest {
   }
 
   @Test
-  public void execute_whenFileContainsOnlySuccessfulRuns_shouldLogCorrectMessage() {
+  public void execute_whenFileContainsOnlySuccessfulRuns_shouldLogCorrectMessage() throws NoSuchFileException {
     sensorSettings.setProperty("sonar.sarifReportPaths", FILE_1);
     ReportAndResults reportAndResults = mockSuccessfulReportAndResults(FILE_1);
 
@@ -110,7 +113,7 @@ public class SarifIssuesImportSensorTest {
   }
 
   @Test
-  public void execute_whenFileContainsOnlyFailedRuns_shouldLogCorrectMessage() {
+  public void execute_whenFileContainsOnlyFailedRuns_shouldLogCorrectMessage() throws NoSuchFileException {
 
     sensorSettings.setProperty("sonar.sarifReportPaths", FILE_1);
     ReportAndResults reportAndResults = mockFailedReportAndResults(FILE_1);
@@ -122,7 +125,7 @@ public class SarifIssuesImportSensorTest {
   }
 
   @Test
-  public void execute_whenFileContainsFailedAndSuccessfulRuns_shouldLogCorrectMessage() {
+  public void execute_whenFileContainsFailedAndSuccessfulRuns_shouldLogCorrectMessage() throws NoSuchFileException {
 
     sensorSettings.setProperty("sonar.sarifReportPaths", FILE_1);
 
@@ -137,7 +140,7 @@ public class SarifIssuesImportSensorTest {
   }
 
   @Test
-  public void execute_whenImportFails_shouldSkipReport() {
+  public void execute_whenImportFails_shouldSkipReport() throws NoSuchFileException {
     sensorSettings.setProperty("sonar.sarifReportPaths", SARIF_REPORT_PATHS_PARAM);
 
     ReportAndResults reportAndResults1 = mockFailedReportAndResults(FILE_1);
@@ -154,7 +157,7 @@ public class SarifIssuesImportSensorTest {
   }
 
   @Test
-  public void execute_whenDeserializationFails_shouldSkipReport() {
+  public void execute_whenDeserializationFails_shouldSkipReport() throws NoSuchFileException {
     sensorSettings.setProperty("sonar.sarifReportPaths", SARIF_REPORT_PATHS_PARAM);
 
     failDeserializingReport(FILE_1);
@@ -168,12 +171,31 @@ public class SarifIssuesImportSensorTest {
     assertSummaryIsCorrectlyDisplayedForSuccessfulFile(FILE_2, reportAndResults2.getSarifImportResults());
   }
 
-  private void failDeserializingReport(String path) {
+  @Test
+  public void execute_whenDeserializationThrowsMessageException_shouldRethrow() throws NoSuchFileException {
+    sensorSettings.setProperty("sonar.sarifReportPaths", FILE_1);
+
+    NoSuchFileException e = new NoSuchFileException("non-existent");
+    failDeserializingReportWithException(FILE_1, e);
+
+    SarifIssuesImportSensor sensor = new SarifIssuesImportSensor(sarifSerializer, sarifImporter, sensorSettings.asConfig());
+    assertThatThrownBy(() -> sensor.execute(sensorContext))
+      .isInstanceOf(MessageException.class)
+      .hasMessage("SARIF report file not found: non-existent");
+
+  }
+
+  private void failDeserializingReport(String path) throws NoSuchFileException {
     Path reportFilePath = sensorContext.fileSystem().resolvePath(path).toPath();
     when(sarifSerializer.deserialize(reportFilePath)).thenThrow(new NullPointerException("deserialization failed"));
   }
 
-  private ReportAndResults mockSuccessfulReportAndResults(String path) {
+  private void failDeserializingReportWithException(String path, Exception exception) throws NoSuchFileException {
+    Path reportFilePath = sensorContext.fileSystem().resolvePath(path).toPath();
+    when(sarifSerializer.deserialize(reportFilePath)).thenThrow(exception);
+  }
+
+  private ReportAndResults mockSuccessfulReportAndResults(String path) throws NoSuchFileException {
     Sarif210 report = mockSarifReport(path);
 
     SarifImportResults sarifImportResults = mock(SarifImportResults.class);
@@ -185,14 +207,14 @@ public class SarifIssuesImportSensorTest {
     return new ReportAndResults(report, sarifImportResults);
   }
 
-  private Sarif210 mockSarifReport(String path) {
+  private Sarif210 mockSarifReport(String path) throws NoSuchFileException {
     Sarif210 report = mock(Sarif210.class);
     Path reportFilePath = sensorContext.fileSystem().resolvePath(path).toPath();
     when(sarifSerializer.deserialize(reportFilePath)).thenReturn(report);
     return report;
   }
 
-  private ReportAndResults mockFailedReportAndResults(String path) {
+  private ReportAndResults mockFailedReportAndResults(String path) throws NoSuchFileException {
     Sarif210 report = mockSarifReport(path);
 
     SarifImportResults sarifImportResults = mock(SarifImportResults.class);
@@ -203,7 +225,7 @@ public class SarifIssuesImportSensorTest {
     return new ReportAndResults(report, sarifImportResults);
   }
 
-  private ReportAndResults mockMixedReportAndResults(String path) {
+  private ReportAndResults mockMixedReportAndResults(String path) throws NoSuchFileException {
     Sarif210 report = mockSarifReport(path);
 
     SarifImportResults sarifImportResults = mock(SarifImportResults.class);