aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-core
diff options
context:
space:
mode:
authorAntoine Vinot <antoine.vinot@sonarsource.com>2022-11-08 12:14:43 +0100
committersonartech <sonartech@sonarsource.com>2022-11-15 20:02:59 +0000
commit59df4a4ad498fa1ce6df396c0b7a6afb70b7ec83 (patch)
tree67292d7f45cac35e36326184db085e115b6e4e14 /sonar-core
parent7b6049377bbeb887442a038efbc119656ebb3a12 (diff)
downloadsonarqube-59df4a4ad498fa1ce6df396c0b7a6afb70b7ec83.tar.gz
sonarqube-59df4a4ad498fa1ce6df396c0b7a6afb70b7ec83.zip
SONAR-17560 Add Sarif deserialization
Diffstat (limited to 'sonar-core')
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/ArtifactLocation.java28
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/CodeFlow.java18
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/Driver.java68
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/Location.java18
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/LocationWrapper.java18
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/PartialFingerprints.java18
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/PhysicalLocation.java18
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/PropertiesBag.java18
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/Region.java26
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/Result.java52
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/Rule.java80
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/Run.java73
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/Sarif210.java28
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializer.java60
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializerImpl.java70
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/ThreadFlow.java18
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/Tool.java18
-rw-r--r--sonar-core/src/main/java/org/sonar/core/sarif/WrappedText.java18
-rw-r--r--sonar-core/src/test/java/org/sonar/core/sarif/RuleTest.java60
-rw-r--r--sonar-core/src/test/java/org/sonar/core/sarif/Sarif210SerializationDeserializationTest.java18
-rw-r--r--sonar-core/src/test/java/org/sonar/core/sarif/SarifSerializerTest.java160
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/sarif/eslint-sarif210.json57
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/sarif/invalid-json-syntax.json8
23 files changed, 781 insertions, 169 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/ArtifactLocation.java b/sonar-core/src/main/java/org/sonar/core/sarif/ArtifactLocation.java
index b9839979c74..f12413c339d 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/ArtifactLocation.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/ArtifactLocation.java
@@ -1,33 +1,45 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
import com.google.gson.annotations.SerializedName;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
public class ArtifactLocation {
- private static final String URI_BASE_ID = "%SRCROOT";
@SerializedName("uri")
private final String uri;
@SerializedName("uriBaseId")
private final String uriBaseId;
- private ArtifactLocation(String uriBaseId, String uri) {
+ public ArtifactLocation(@Nullable String uriBaseId, String uri) {
this.uriBaseId = uriBaseId;
this.uri = uri;
}
- public static ArtifactLocation of(String uri) {
- return new ArtifactLocation(URI_BASE_ID, uri);
- }
-
public String getUri() {
return uri;
}
+ @CheckForNull
public String getUriBaseId() {
return uriBaseId;
}
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/CodeFlow.java b/sonar-core/src/main/java/org/sonar/core/sarif/CodeFlow.java
index 0ee64717140..887ba202215 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/CodeFlow.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/CodeFlow.java
@@ -1,7 +1,21 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Driver.java b/sonar-core/src/main/java/org/sonar/core/sarif/Driver.java
index cbbbe3b32a3..aaa8d9faac2 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/Driver.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/Driver.java
@@ -1,16 +1,30 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
import com.google.gson.annotations.SerializedName;
import java.util.Set;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
public class Driver {
- private static final String TOOL_NAME = "SonarQube";
- private static final String ORGANIZATION_NAME = "SonarSource";
@SerializedName("name")
private final String name;
@@ -21,11 +35,7 @@ public class Driver {
@SerializedName("rules")
private final Set<Rule> rules;
- public Driver(String semanticVersion, Set<Rule> rules) {
- this(TOOL_NAME, ORGANIZATION_NAME, semanticVersion, rules);
- }
-
- private Driver(String name, String organization, String semanticVersion, Set<Rule> rules) {
+ private Driver(String name, @Nullable String organization, @Nullable String semanticVersion, Set<Rule> rules) {
this.name = name;
this.organization = organization;
this.semanticVersion = semanticVersion;
@@ -36,10 +46,12 @@ public class Driver {
return name;
}
+ @CheckForNull
public String getOrganization() {
return organization;
}
+ @CheckForNull
public String getSemanticVersion() {
return semanticVersion;
}
@@ -47,4 +59,42 @@ public class Driver {
public Set<Rule> getRules() {
return rules;
}
+
+ public static DriverBuilder builder() {
+ return new DriverBuilder();
+ }
+
+ public static final class DriverBuilder {
+ private String name;
+ private String organization;
+ private String semanticVersion;
+ private Set<Rule> rules;
+
+ private DriverBuilder() {
+ }
+
+ public DriverBuilder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public DriverBuilder organization(String organization) {
+ this.organization = organization;
+ return this;
+ }
+
+ public DriverBuilder semanticVersion(String semanticVersion) {
+ this.semanticVersion = semanticVersion;
+ return this;
+ }
+
+ public DriverBuilder rules(Set<Rule> rules) {
+ this.rules = rules;
+ return this;
+ }
+
+ public Driver build() {
+ return new Driver(name, organization, semanticVersion, rules);
+ }
+ }
}
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Location.java b/sonar-core/src/main/java/org/sonar/core/sarif/Location.java
index c2a334c9bd9..ae1db296947 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/Location.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/Location.java
@@ -1,7 +1,21 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/LocationWrapper.java b/sonar-core/src/main/java/org/sonar/core/sarif/LocationWrapper.java
index 2c551204713..91fa55680fe 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/LocationWrapper.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/LocationWrapper.java
@@ -1,7 +1,21 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/PartialFingerprints.java b/sonar-core/src/main/java/org/sonar/core/sarif/PartialFingerprints.java
index 67cbbdef1d6..ffef750f531 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/PartialFingerprints.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/PartialFingerprints.java
@@ -1,7 +1,21 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/PhysicalLocation.java b/sonar-core/src/main/java/org/sonar/core/sarif/PhysicalLocation.java
index c4c1e833944..0d9b7582c84 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/PhysicalLocation.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/PhysicalLocation.java
@@ -1,7 +1,21 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/PropertiesBag.java b/sonar-core/src/main/java/org/sonar/core/sarif/PropertiesBag.java
index 1f44afc39ac..949f3fea3ef 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/PropertiesBag.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/PropertiesBag.java
@@ -1,7 +1,21 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Region.java b/sonar-core/src/main/java/org/sonar/core/sarif/Region.java
index 8fd89fa4c41..e909fceb9c3 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/Region.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/Region.java
@@ -1,7 +1,21 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
@@ -45,10 +59,10 @@ public class Region {
}
public static final class RegionBuilder {
- private int startLine;
- private int endLine;
- private int startColumn;
- private int endColumn;
+ private Integer startLine;
+ private Integer endLine;
+ private Integer startColumn;
+ private Integer endColumn;
public RegionBuilder startLine(int startLine) {
this.startLine = startLine;
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Result.java b/sonar-core/src/main/java/org/sonar/core/sarif/Result.java
index 3815da4a480..60f980de875 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/Result.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/Result.java
@@ -1,14 +1,30 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
import com.google.gson.annotations.SerializedName;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
-import org.sonar.api.rule.RuleKey;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
public class Result {
@SerializedName("ruleId")
@@ -16,19 +32,19 @@ public class Result {
@SerializedName("message")
private final WrappedText message;
@SerializedName("locations")
- private final Set<Location> locations;
+ private final LinkedHashSet<Location> locations;
@SerializedName("partialFingerprints")
private final PartialFingerprints partialFingerprints;
@SerializedName("codeFlows")
private final List<CodeFlow> codeFlows;
-
- private Result(RuleKey ruleKey, String message, Location location, String primaryLocationLineHash, List<CodeFlow> codeFlows) {
- this.ruleId = ruleKey.toString();
+ private Result(String ruleId, String message, LinkedHashSet<Location> locations,
+ @Nullable String primaryLocationLineHash, @Nullable List<CodeFlow> codeFlows) {
+ this.ruleId = ruleId;
this.message = WrappedText.of(message);
- this.locations = Set.of(location);
- this.partialFingerprints = new PartialFingerprints(primaryLocationLineHash);
- this.codeFlows = List.copyOf(codeFlows);
+ this.locations = locations;
+ this.partialFingerprints = primaryLocationLineHash == null ? null : new PartialFingerprints(primaryLocationLineHash);
+ this.codeFlows = codeFlows == null ? null : List.copyOf(codeFlows);
}
public String getRuleId() {
@@ -43,10 +59,12 @@ public class Result {
return locations;
}
+ @CheckForNull
public PartialFingerprints getPartialFingerprints() {
return partialFingerprints;
}
+ @CheckForNull
public List<CodeFlow> getCodeFlows() {
return codeFlows;
}
@@ -56,17 +74,17 @@ public class Result {
}
public static final class ResultBuilder {
- private RuleKey ruleKey;
+ private String ruleId;
private String message;
- private Location location;
+ private LinkedHashSet<Location> locations;
private String hash;
private List<CodeFlow> codeFlows;
private ResultBuilder() {
}
- public ResultBuilder ruleKey(RuleKey ruleKey) {
- this.ruleKey = ruleKey;
+ public ResultBuilder ruleId(String ruleId) {
+ this.ruleId = ruleId;
return this;
}
@@ -75,8 +93,8 @@ public class Result {
return this;
}
- public ResultBuilder locations(Location location) {
- this.location = location;
+ public ResultBuilder locations(Set<Location> locations) {
+ this.locations = new LinkedHashSet<>(locations);
return this;
}
@@ -91,7 +109,7 @@ public class Result {
}
public Result build() {
- return new Result(ruleKey, message, location, hash, codeFlows);
+ return new Result(ruleId, message, locations, hash, codeFlows);
}
}
}
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Rule.java b/sonar-core/src/main/java/org/sonar/core/sarif/Rule.java
index ce234118159..eb4e140ae64 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/Rule.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/Rule.java
@@ -1,13 +1,26 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
import com.google.gson.annotations.SerializedName;
import java.util.Objects;
-import org.sonar.api.rule.RuleKey;
public class Rule {
@SerializedName("id")
@@ -23,12 +36,12 @@ public class Rule {
@SerializedName("properties")
private final PropertiesBag properties;
- public Rule(RuleKey ruleKey, String ruleName, String ruleDescription, PropertiesBag properties) {
- id = ruleKey.toString();
- name = ruleKey.toString();
- shortDescription = WrappedText.of(ruleName);
- fullDescription = WrappedText.of(ruleName);
- help = WrappedText.of(ruleDescription);
+ private Rule(String id, String name, WrappedText shortDescription, WrappedText fullDescription, WrappedText help, PropertiesBag properties) {
+ this.id = id;
+ this.name = name;
+ this.shortDescription = shortDescription;
+ this.fullDescription = fullDescription;
+ this.help = help;
this.properties = properties;
}
@@ -73,4 +86,53 @@ public class Rule {
return Objects.hash(id);
}
+ public static RuleBuilder builder() {
+ return new RuleBuilder();
+ }
+
+ public static final class RuleBuilder {
+ private String id;
+ private String name;
+ private WrappedText shortDescription;
+ private WrappedText fullDescription;
+ private WrappedText help;
+ private PropertiesBag properties;
+
+ private RuleBuilder() {
+ }
+
+ public RuleBuilder id(String id) {
+ this.id = id;
+ return this;
+ }
+
+ public RuleBuilder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public RuleBuilder shortDescription(String shortDescription) {
+ this.shortDescription = WrappedText.of(shortDescription);
+ return this;
+ }
+
+ public RuleBuilder fullDescription(String fullDescription) {
+ this.fullDescription = WrappedText.of(fullDescription);
+ return this;
+ }
+
+ public RuleBuilder help(String help) {
+ this.help = WrappedText.of(help);
+ return this;
+ }
+
+ public RuleBuilder properties(PropertiesBag properties) {
+ this.properties = properties;
+ return this;
+ }
+
+ public Rule build() {
+ return new Rule(id, name, shortDescription, fullDescription, help, properties);
+ }
+ }
}
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Run.java b/sonar-core/src/main/java/org/sonar/core/sarif/Run.java
index ae8cc0a78e4..ebcf81055fa 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/Run.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/Run.java
@@ -1,21 +1,31 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
-import com.google.common.annotations.VisibleForTesting;
import com.google.gson.annotations.SerializedName;
import java.util.Set;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
public class Run {
- @VisibleForTesting
- public static final String LANGUAGE_EN_US = "en-us";
- @VisibleForTesting
- public static final String COLUMN_KIND = "utf16CodeUnits";
-
@SerializedName("tool")
private final Tool tool;
@SerializedName("results")
@@ -25,21 +35,19 @@ public class Run {
@SerializedName("columnKind")
private final String columnKind;
- public Run(Tool tool, Set<Result> results) {
- this(tool, results, LANGUAGE_EN_US, COLUMN_KIND);
- }
-
- private Run(Tool tool, Set<Result> results, String language, String columnKind) {
+ private Run(Tool tool, Set<Result> results, @Nullable String language, @Nullable String columnKind) {
this.tool = tool;
this.results = Set.copyOf(results);
this.language = language;
this.columnKind = columnKind;
}
+ @CheckForNull
public String getLanguage() {
return language;
}
+ @CheckForNull
public String getColumnKind() {
return columnKind;
}
@@ -51,4 +59,43 @@ public class Run {
public Set<Result> getResults() {
return results;
}
+
+ public static RunBuilder builder() {
+ return new RunBuilder();
+ }
+
+ public static final class RunBuilder {
+ private Tool tool;
+ private Set<Result> results;
+ private String language;
+ private String columnKind;
+
+ private RunBuilder() {
+ }
+
+ public RunBuilder tool(Tool tool) {
+ this.tool = tool;
+ return this;
+ }
+
+ public RunBuilder results(Set<Result> results) {
+ this.results = results;
+ return this;
+ }
+
+ public RunBuilder language(String language) {
+ this.language = language;
+ return this;
+ }
+
+ public RunBuilder columnKind(String columnKind) {
+ this.columnKind = columnKind;
+ return this;
+ }
+
+ public Run build() {
+ return new Run(tool, results, language, columnKind);
+ }
+ }
+
}
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Sarif210.java b/sonar-core/src/main/java/org/sonar/core/sarif/Sarif210.java
index d19c386461f..0df616af2e2 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/Sarif210.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/Sarif210.java
@@ -1,7 +1,21 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
@@ -12,8 +26,6 @@ import java.util.Set;
public class Sarif210 {
@VisibleForTesting
- public static final String SARIF_SCHEMA_URL = "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json";
- @VisibleForTesting
public static final String SARIF_VERSION = "2.1.0";
@SerializedName("version")
@@ -23,13 +35,9 @@ public class Sarif210 {
@SerializedName("runs")
private final Set<Run> runs;
- public Sarif210(Run run) {
- this(SARIF_SCHEMA_URL, SARIF_VERSION, run);
- }
-
- private Sarif210(String schema, String version, Run run) {
+ public Sarif210(String schema, Run run) {
this.schema = schema;
- this.version = version;
+ this.version = SARIF_VERSION;
this.runs = Set.of(run);
}
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializer.java b/sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializer.java
index 62c2452d896..1f984da096e 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializer.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializer.java
@@ -1,49 +1,29 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.gson.Gson;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.util.Base64;
-import java.util.zip.GZIPOutputStream;
-import javax.inject.Inject;
-import org.sonar.api.ce.ComputeEngineSide;
+import java.nio.file.Path;
-import static java.nio.charset.StandardCharsets.UTF_8;
+public interface SarifSerializer {
-@ComputeEngineSide
-public class SarifSerializer {
- private final Gson gson;
+ String serialize(Sarif210 sarif210);
- @Inject
- public SarifSerializer() {
- this(new Gson());
- }
-
- @VisibleForTesting
- SarifSerializer(Gson gson) {
- this.gson = gson;
- }
-
- public String serializeAndEncode(Sarif210 sarif210) {
- String serializedSarif = gson.toJson(sarif210);
- return compressToGzipAndEncodeBase64(serializedSarif);
- }
-
- private static String compressToGzipAndEncodeBase64(String input) {
- try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- GZIPOutputStream gzipStream = new GZIPOutputStream(outputStream)) {
- gzipStream.write(input.getBytes(UTF_8));
- gzipStream.finish();
- return Base64.getEncoder().encodeToString(outputStream.toByteArray());
- } catch (IOException e) {
- throw new UncheckedIOException(String.format("Failed to compress and encode the input: %s", input), e);
- }
- }
+ Sarif210 deserialize(Path sarifPath);
}
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializerImpl.java b/sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializerImpl.java
new file mode 100644
index 00000000000..3f33419cb87
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializerImpl.java
@@ -0,0 +1,70 @@
+/*
+ * 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.core.sarif;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.gson.Gson;
+import com.google.gson.JsonIOException;
+import com.google.gson.JsonSyntaxException;
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.file.Path;
+import javax.inject.Inject;
+import org.sonar.api.ce.ComputeEngineSide;
+import org.sonar.api.scanner.ScannerSide;
+
+import static java.lang.String.format;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.nio.file.Files.newBufferedReader;
+
+@ScannerSide
+@ComputeEngineSide
+public class SarifSerializerImpl implements SarifSerializer {
+ private static final String SARIF_REPORT_ERROR = "Failed to read SARIF report at '%s'";
+ private static final String SARIF_JSON_SYNTAX_ERROR = SARIF_REPORT_ERROR + ": invalid JSON syntax";
+
+ private final Gson gson;
+
+ @Inject
+ public SarifSerializerImpl() {
+ this(new Gson());
+ }
+
+ @VisibleForTesting
+ SarifSerializerImpl(Gson gson) {
+ this.gson = gson;
+ }
+
+ @Override
+ public String serialize(Sarif210 sarif210) {
+ return gson.toJson(sarif210);
+ }
+
+ @Override
+ public Sarif210 deserialize(Path reportPath) {
+ try (Reader reader = newBufferedReader(reportPath, UTF_8)) {
+ return gson.fromJson(reader, Sarif210.class);
+ } 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);
+ }
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/ThreadFlow.java b/sonar-core/src/main/java/org/sonar/core/sarif/ThreadFlow.java
index 45d75c0bdc0..e8cd950fda6 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/ThreadFlow.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/ThreadFlow.java
@@ -1,7 +1,21 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Tool.java b/sonar-core/src/main/java/org/sonar/core/sarif/Tool.java
index 3990f8447f8..7a10feea395 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/Tool.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/Tool.java
@@ -1,7 +1,21 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/WrappedText.java b/sonar-core/src/main/java/org/sonar/core/sarif/WrappedText.java
index ddf259342f6..06539aaa6d0 100644
--- a/sonar-core/src/main/java/org/sonar/core/sarif/WrappedText.java
+++ b/sonar-core/src/main/java/org/sonar/core/sarif/WrappedText.java
@@ -1,7 +1,21 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
diff --git a/sonar-core/src/test/java/org/sonar/core/sarif/RuleTest.java b/sonar-core/src/test/java/org/sonar/core/sarif/RuleTest.java
index e579f8c3571..6714bbcb3e1 100644
--- a/sonar-core/src/test/java/org/sonar/core/sarif/RuleTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/sarif/RuleTest.java
@@ -1,17 +1,28 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
import java.util.Set;
-import org.apache.commons.lang.RandomStringUtils;
import org.junit.Test;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.core.sarif.PropertiesBag;
-import org.sonar.core.sarif.Rule;
+import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.assertj.core.api.Assertions.assertThat;
@@ -19,34 +30,51 @@ public class RuleTest {
@Test
public void equals_matchOnlyOnId() {
- Rule rule1 = createRule("rep1", "rule1");
- Rule rule1Bis = createRule("rep1", "rule1");
- Rule rule2 = withRuleId(rule1, "rep1", "rule2");
+ Rule rule1 = createRule();
+ Rule rule1Bis = createRule(rule1.getId()) ;
+ Rule rule2 = withRuleId(rule1, rule1.getId() + randomAlphanumeric(3));
assertThat(rule1).isEqualTo(rule1Bis).isNotEqualTo(rule2);
}
@Test
public void equals_notMatchWithNull(){
- Rule rule1 = createRule("rep1", "rule2");
+ Rule rule1 = createRule();
assertThat(rule1).isNotEqualTo(null);
}
@Test
public void equals_matchWithSameObject(){
- Rule rule1 = createRule("rep5", "rule2");
+ Rule rule1 = createRule();
assertThat(rule1).isEqualTo(rule1);
}
- private static Rule withRuleId(Rule rule, String repoName, String ruleName) {
- return new Rule(RuleKey.of(repoName, ruleName), rule.getName(), rule.getFullDescription().getText(), rule.getProperties());
+ private static Rule withRuleId(Rule rule, String id) {
+ return Rule.builder()
+ .id(id)
+ .name(rule.getName())
+ .shortDescription(rule.getName())
+ .fullDescription(rule.getName())
+ .help(rule.getFullDescription().getText())
+ .properties(rule.getProperties())
+ .build();
}
- private static Rule createRule(String repoName, String ruleName) {
- return new Rule(RuleKey.of(repoName, ruleName), RandomStringUtils.randomAlphanumeric(5), RandomStringUtils.randomAlphanumeric(5),
- PropertiesBag.of(RandomStringUtils.randomAlphanumeric(3), Set.of(RandomStringUtils.randomAlphanumeric(4))));
+ private static Rule createRule() {
+ return createRule(randomAlphanumeric(5));
+ }
+
+ private static Rule createRule(String id) {
+ return Rule.builder()
+ .id(id)
+ .name(randomAlphanumeric(5))
+ .shortDescription(randomAlphanumeric(5))
+ .fullDescription(randomAlphanumeric(10))
+ .help(randomAlphanumeric(10))
+ .properties(PropertiesBag.of(randomAlphanumeric(3), Set.of(randomAlphanumeric(4))))
+ .build();
}
}
diff --git a/sonar-core/src/test/java/org/sonar/core/sarif/Sarif210SerializationDeserializationTest.java b/sonar-core/src/test/java/org/sonar/core/sarif/Sarif210SerializationDeserializationTest.java
index ef40fe8dcd5..e603ada42e9 100644
--- a/sonar-core/src/test/java/org/sonar/core/sarif/Sarif210SerializationDeserializationTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/sarif/Sarif210SerializationDeserializationTest.java
@@ -1,7 +1,21 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
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
index e239a5e859f..8350226ce75 100644
--- a/sonar-core/src/test/java/org/sonar/core/sarif/SarifSerializerTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/sarif/SarifSerializerTest.java
@@ -1,43 +1,161 @@
/*
- * Copyright (C) 2017-2022 SonarSource SA
- * All rights reserved
+ * 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.core.sarif;
-import com.google.gson.Gson;
-import org.sonar.core.sarif.Sarif210;
+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.InjectMocks;
-import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
-import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+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;
@RunWith(MockitoJUnitRunner.class)
public class SarifSerializerTest {
- private static final String SARIF_JSON = "{\"message\" : \"A sarif in json format as String.\"}";
- private static final String SARIF_JSON_ENCODED = "H4sIAAAAAAAAAKtWyk0tLk5MT1VSsFJQclQoTizKTFPIzFPIKs7PU0jLL8pNLFFILFYILinKzEvXU6oFACgK7/YxAAAA";
+ private static final String SARIF_JSON = "{\"version\":\"2.1.0\",\"$schema\":\"http://json.schemastore.org/sarif-2.1.0-rtm.4\",\"runs\":[{\"results\":[]}]}";
- @Mock
- private Gson gson;
+ private final SarifSerializerImpl serializer = new SarifSerializerImpl();
- @InjectMocks
- private SarifSerializer serializer;
+ @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 serializeAndEncode_should_compressInGZipAndEncodeBase64() {
- when(gson.toJson(any(Sarif210.class))).thenReturn(SARIF_JSON);
- Sarif210 sarif210 = mock(Sarif210.class);
+ public void deserialize_shouldFail_whenFileCantBeFound() {
+ String file = "wrongPathToFile";
+ Path sarif = Paths.get(file);
+
+ assertThatThrownBy(() -> serializer.deserialize(sarif))
+ .isInstanceOf(IllegalStateException.class)
+ .hasMessage(String.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(String.format("Failed to read SARIF report at '%s': invalid JSON syntax", sarif));
+ }
+
+ 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);
- String encoded = serializer.serializeAndEncode(sarif210);
+ 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"));
+ }
- assertThat(encoded).isEqualTo(SARIF_JSON_ENCODED);
+ 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/resources/org/sonar/core/sarif/eslint-sarif210.json b/sonar-core/src/test/resources/org/sonar/core/sarif/eslint-sarif210.json
new file mode 100644
index 00000000000..3d7d3445738
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/sarif/eslint-sarif210.json
@@ -0,0 +1,57 @@
+{
+ "version": "2.1.0",
+ "$schema": "http://json.schemastore.org/sarif-2.1.0-rtm.4",
+ "runs": [
+ {
+ "tool": {
+ "driver": {
+ "name": "ESLint",
+ "informationUri": "https://eslint.org",
+ "rules": [
+ {
+ "id": "no-unused-vars",
+ "shortDescription": {
+ "text": "disallow unused variables"
+ },
+ "helpUri": "https://eslint.org/docs/rules/no-unused-vars",
+ "properties": {
+ "category": "Variables"
+ }
+ }
+ ]
+ }
+ },
+ "artifacts": [
+ {
+ "location": {
+ "uri": "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js"
+ }
+ }
+ ],
+ "results": [
+ {
+ "level": "error",
+ "message": {
+ "text": "'x' is assigned a value but never used."
+ },
+ "locations": [
+ {
+ "physicalLocation": {
+ "artifactLocation": {
+ "uri": "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js",
+ "index": 0
+ },
+ "region": {
+ "startLine": 1,
+ "startColumn": 5
+ }
+ }
+ }
+ ],
+ "ruleId": "no-unused-vars",
+ "ruleIndex": 0
+ }
+ ]
+ }
+ ]
+}
diff --git a/sonar-core/src/test/resources/org/sonar/core/sarif/invalid-json-syntax.json b/sonar-core/src/test/resources/org/sonar/core/sarif/invalid-json-syntax.json
new file mode 100644
index 00000000000..eff20eb286a
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/sarif/invalid-json-syntax.json
@@ -0,0 +1,8 @@
+{
+ "version": "2.1.0",
+ "$schema": "http://json.schemastore.org/sarif-2.1.0-rtm.4",
+ "runs":
+ {
+
+ }
+}