github.com/reviewdog/reviewdog@v0.17.5-0.20240516205324-0cd103a83d58/parser/sarif_test.go (about)

     1  package parser
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/google/go-cmp/cmp"
    10  	"github.com/reviewdog/reviewdog/service/serviceutil"
    11  	"google.golang.org/protobuf/encoding/protojson"
    12  )
    13  
    14  func TestExampleSarifParser(t *testing.T) {
    15  	p := NewSarifParser()
    16  	for i, fixture := range fixtures {
    17  		diagnostics, err := p.Parse(strings.NewReader(fixture[0]))
    18  		if err != nil {
    19  			panic(err)
    20  		}
    21  		if len(diagnostics) == 0 {
    22  			t.Errorf("empty diagnostics")
    23  		}
    24  		for _, d := range diagnostics {
    25  			rdjson, err := protojson.MarshalOptions{Indent: "  "}.Marshal(d)
    26  			if err != nil {
    27  				t.Fatal(err)
    28  			}
    29  			var actualJSON map[string]any
    30  			var expectJSON map[string]any
    31  			if err := json.Unmarshal(rdjson, &actualJSON); err != nil {
    32  				t.Fatal(err)
    33  			}
    34  			if err := json.Unmarshal([]byte(fixture[1]), &expectJSON); err != nil {
    35  				t.Fatal(err)
    36  			}
    37  			expectJSON["originalOutput"] = actualJSON["originalOutput"]
    38  			if diff := cmp.Diff(actualJSON, expectJSON); diff != "" {
    39  				t.Errorf("fixtures[%d] (-got, +want):\n%s", i, diff)
    40  			}
    41  		}
    42  	}
    43  }
    44  
    45  func basedir() string {
    46  	root, err := serviceutil.GetGitRoot()
    47  	if err != nil {
    48  		panic(err)
    49  	}
    50  	return root
    51  }
    52  
    53  var fixtures = [][]string{{
    54  	fmt.Sprintf(`{
    55  	"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
    56  	"version": "2.1.0",
    57  	"runs": [
    58  		{
    59  			"originalUriBaseIds": {
    60  				"SRCROOT": {
    61  					"uri": "file://%s"
    62  				}
    63  			},
    64  			"results": [
    65  				{
    66  					"level": "warning",
    67  					"locations": [
    68  						{
    69  							"physicalLocation": {
    70  								"artifactLocation": {
    71  									"uri": "src/MyClass.kt",
    72  									"uriBaseId": "SRCROOT"
    73  								},
    74  								"region": {
    75  									"startLine": 10,
    76  									"startColumn": 5,
    77  									"endLine": 12,
    78  									"endColumn": 15
    79  								}
    80  							}
    81  						}
    82  					],
    83  					"message": {
    84  						"text": "result message"
    85  					},
    86  					"ruleId": "rule_id"
    87  				}
    88  			],
    89  			"tool": {
    90  				"driver": {
    91  					"informationUri": "https://example.com",
    92  					"name": "driver_name",
    93  					"rules": [
    94  						{
    95  							"helpUri": "https://example.com",
    96  							"id": "rule_id",
    97  							"name": "My Rule",
    98  							"shortDescription": {
    99  								"text": "Rule description"
   100  							}
   101  						}
   102  					]
   103  				}
   104  			}
   105  		}
   106  	]
   107  }`, basedir()), `{
   108  	"message": "result message",
   109  	"location": {
   110  		"path": "src/MyClass.kt",
   111  		"range": {
   112  			"start": {
   113  				"line": 10,
   114  				"column": 5
   115  			},
   116  			"end": {
   117  				"line": 12,
   118  				"column": 15
   119  			}
   120  		}
   121  	},
   122  	"severity": "WARNING",
   123  	"source": {
   124  		"name": "driver_name",
   125  		"url": "https://example.com"
   126  	},
   127  	"code": {
   128  		"value": "rule_id",
   129  		"url": "https://example.com"
   130  	}
   131  }`},
   132  	{`{
   133  	"runs": [
   134  		{
   135  			"originalUriBaseIds": {
   136  				"SRCROOT": {
   137  					"description": "uri deleted root"
   138  				}
   139  			},
   140  			"results": [
   141  				{
   142  					"locations": [
   143  						{
   144  							"physicalLocation": {
   145  								"artifactLocation": {
   146  									"uri": "src/MyClass.kt",
   147  									"uriBaseId": "SRCROOT"
   148  								},
   149  								"region": {
   150  									"startLine": 10
   151  								}
   152  							}
   153  						}
   154  					],
   155  					"message": {
   156  						"text": "message"
   157  					},
   158  					"ruleId": "rule_id"
   159  				}
   160  			],
   161  			"tool": {
   162  				"driver": {
   163  					"name": "driver_name",
   164  					"rules": [
   165  						{
   166  							"id": "rule_id",
   167  							"defaultConfiguration": {
   168  								"level": "error"
   169  							}
   170  						}
   171  					]
   172  				}
   173  			}
   174  		}
   175  	]
   176  }`, `{
   177  	"message": "message",
   178  	"location": {
   179  		"path": "src/MyClass.kt",
   180  		"range": {
   181  			"start": {
   182  				"line": 10
   183  			}
   184  		}
   185  	},
   186  	"severity": "ERROR",
   187  	"source": {
   188  		"name": "driver_name"
   189  	},
   190  	"code": {
   191  		"value": "rule_id"
   192  	}
   193  }`},
   194  	{`{
   195  	"runs": [
   196  		{
   197  			"results": [
   198  				{
   199  					"locations": [
   200  						{
   201  							"physicalLocation": {
   202  								"artifactLocation": {
   203  									"uri": "src/MyClass.kt"
   204  								},
   205  								"region": {
   206  									"startLine": 10
   207  								}
   208  							}
   209  						}
   210  					],
   211  					"fixes": [
   212  						{
   213  							"artifactChanges": [
   214  								{
   215  									"artifactLocation": {
   216  										"uri": "src/MyClass.kt"
   217  									},
   218  									"replacements": [
   219  										{
   220  											"deletedRegion": {
   221  												"startLine": 10,
   222  												"startColumn": 1,
   223  												"endColumn": 1
   224  											},
   225  											"insertedContent": {
   226  												"text": "// "
   227  											}
   228  										}
   229  									]
   230  								}
   231  							]
   232  						}
   233  					],
   234  					"message": {
   235  						"markdown": "message"
   236  					},
   237  					"ruleId": "rule_id"
   238  				}
   239  			],
   240  			"tool": {
   241  				"driver": {
   242  					"name": "driver_name"
   243  				}
   244  			}
   245  		}
   246  	]
   247  }`, `{
   248  	"message": "message",
   249  	"location": {
   250  		"path": "src/MyClass.kt",
   251  		"range": {
   252  			"start": {
   253  				"line": 10
   254  			}
   255  		}
   256  	},
   257  	"source": {
   258  		"name": "driver_name"
   259  	},
   260  	"code": {
   261  		"value": "rule_id"
   262  	},
   263  	"suggestions": [
   264  		{
   265  			"range": {
   266  				"start": {
   267  					"line": 10,
   268  					"column": 1
   269  				},
   270  				"end": {
   271  					"line": 10,
   272  					"column": 1
   273  				}
   274  			},
   275  			"text": "// "
   276  		}
   277  	]
   278  }`},
   279  	{fmt.Sprintf(`{
   280  	"runs": [
   281  	  {
   282  		"originalUriBaseIds": {
   283  			"ROOTPATH": {
   284  			  "uri": "%s"
   285  			}
   286  		  },
   287  		"tool": {
   288  		  "driver": {
   289  			"name": "Trivy",
   290  			"informationUri": "https://github.com/aquasecurity/trivy",
   291  			"fullName": "Trivy Vulnerability Scanner",
   292  			"version": "0.15.0",
   293  			"rules": [
   294  			  {
   295  				"id": "CVE-2018-14618/curl",
   296  				"name": "OS Package Vulnerability (Alpine)",
   297  				"shortDescription": {
   298  				  "text": "CVE-2018-14618 Package: curl"
   299  				},
   300  				"fullDescription": {
   301  				  "text": "curl: NTLM password overflow via integer overflow."
   302  				},
   303  				"defaultConfiguration": {
   304  				  "level": "error"
   305  				},
   306  				"helpUri": "https://avd.aquasec.com/nvd/cve-2018-14618",
   307  				"help": {
   308  				  "text": "Vulnerability CVE-2018-14618\nSeverity: CRITICAL\n...",
   309  				  "markdown": "**Vulnerability CVE-2018-14618**\n| Severity..."
   310  				},
   311  				"properties": {
   312  				  "tags": [
   313  					"vulnerability",
   314  					"CRITICAL",
   315  					"curl"
   316  				  ],
   317  				  "precision": "very-high"
   318  				}
   319  			  }
   320  			]
   321  		  }
   322  		},
   323  		"results": [
   324  		  {
   325  			"ruleId": "CVE-2018-14618/curl",
   326  			"ruleIndex": 0,
   327  			"level": "error",
   328  			"message": {
   329  			  "text": "curl before version 7.61.1 is..."
   330  			},
   331  			"locations": [{
   332  			  "physicalLocation": {
   333  				"artifactLocation": {
   334  				  "uri": "knqyf263/vuln-image (alpine 3.7.1)",
   335  				  "uriBaseId": "ROOTPATH"
   336  				}
   337  			  }
   338  			}]
   339  		  }]
   340  	  }
   341  	]
   342    }
   343  `, basedir()), `{
   344  	"message": "curl before version 7.61.1 is...",
   345  	"location": {
   346  		"path": "knqyf263/vuln-image (alpine 3.7.1)"
   347  	},
   348  	"severity": "ERROR",
   349  	"source": {
   350  		"name": "Trivy",
   351  		"url": "https://github.com/aquasecurity/trivy"
   352  	},
   353  	"code": {
   354  		"value": "CVE-2018-14618/curl",
   355  		"url": "https://avd.aquasec.com/nvd/cve-2018-14618"
   356  	}
   357  }`},
   358  }