diff options
Diffstat (limited to '')
-rw-r--r-- | test/test_formatter_sarif.py | 120 |
1 files changed, 76 insertions, 44 deletions
diff --git a/test/test_formatter_sarif.py b/test/test_formatter_sarif.py index 026d336..982bb6e 100644 --- a/test/test_formatter_sarif.py +++ b/test/test_formatter_sarif.py @@ -1,4 +1,5 @@ """Test the codeclimate JSON formatter.""" + from __future__ import annotations import json @@ -13,54 +14,75 @@ import pytest from ansiblelint.errors import MatchError from ansiblelint.file_utils import Lintable from ansiblelint.formatters import SarifFormatter -from ansiblelint.rules import AnsibleLintRule +from ansiblelint.rules import AnsibleLintRule, RulesCollection class TestSarifFormatter: """Unit test for SarifFormatter.""" - rule = AnsibleLintRule() + rule1 = AnsibleLintRule() + rule2 = AnsibleLintRule() matches: list[MatchError] = [] formatter: SarifFormatter | None = None + collection = RulesCollection() + collection.register(rule1) + collection.register(rule2) def setup_class(self) -> None: """Set up few MatchError objects.""" - self.rule = AnsibleLintRule() - self.rule.id = "TCF0001" - self.rule.severity = "VERY_HIGH" - self.rule.description = "This is the rule description." - self.rule.link = "https://rules/help#TCF0001" - self.rule.tags = ["tag1", "tag2"] - self.matches = [] - self.matches.append( - MatchError( - message="message", - lineno=1, - column=10, - details="details", - lintable=Lintable("filename.yml", content=""), - rule=self.rule, - tag="yaml[test]", - ), - ) - self.matches.append( - MatchError( - message="message", - lineno=2, - details="", - lintable=Lintable("filename.yml", content=""), - rule=self.rule, - tag="yaml[test]", - ), + self.rule1.id = "TCF0001" + self.rule1.severity = "VERY_HIGH" + self.rule1.description = "This is the rule description." + self.rule1.link = "https://rules/help#TCF0001" + self.rule1.tags = ["tag1", "tag2"] + + self.rule2.id = "TCF0002" + self.rule2.severity = "MEDIUM" + self.rule2.link = "https://rules/help#TCF0002" + self.rule2.tags = ["tag3", "tag4"] + + self.matches.extend( + [ + MatchError( + message="message1", + lineno=1, + column=10, + details="details1", + lintable=Lintable("filename1.yml", content=""), + rule=self.rule1, + tag="yaml[test1]", + ignored=False, + ), + MatchError( + message="message2", + lineno=2, + details="", + lintable=Lintable("filename2.yml", content=""), + rule=self.rule1, + tag="yaml[test2]", + ignored=True, + ), + MatchError( + message="message3", + lineno=666, + column=667, + details="details3", + lintable=Lintable("filename3.yml", content=""), + rule=self.rule2, + tag="yaml[test3]", + ignored=False, + ), + ], ) + self.formatter = SarifFormatter(pathlib.Path.cwd(), display_relative_path=True) - def test_format_list(self) -> None: + def test_sarif_format_list(self) -> None: """Test if the return value is a string.""" assert isinstance(self.formatter, SarifFormatter) assert isinstance(self.formatter.format_result(self.matches), str) - def test_result_is_json(self) -> None: + def test_sarif_result_is_json(self) -> None: """Test if returned string value is a JSON.""" assert isinstance(self.formatter, SarifFormatter) output = self.formatter.format_result(self.matches) @@ -68,17 +90,22 @@ class TestSarifFormatter: # https://github.com/ansible/ansible-navigator/issues/1490 assert "\n" not in output - def test_single_match(self) -> None: + def test_sarif_single_match(self) -> None: """Test negative case. Only lists are allowed. Otherwise, a RuntimeError will be raised.""" assert isinstance(self.formatter, SarifFormatter) - with pytest.raises(RuntimeError): + with pytest.raises(TypeError): self.formatter.format_result(self.matches[0]) # type: ignore[arg-type] - def test_result_is_list(self) -> None: - """Test if the return SARIF object contains the results with length of 2.""" + def test_sarif_format(self) -> None: + """Test if the return SARIF object contains the expected results.""" assert isinstance(self.formatter, SarifFormatter) sarif = json.loads(self.formatter.format_result(self.matches)) - assert len(sarif["runs"][0]["results"]) == 2 + assert len(sarif["runs"][0]["results"]) == 3 + for result in sarif["runs"][0]["results"]: + # Ensure all reported entries have a level + assert "level" in result + # Ensure reported levels are either error or warning + assert result["level"] in ("error", "warning") def test_validate_sarif_schema(self) -> None: """Test if the returned JSON is a valid SARIF report.""" @@ -90,16 +117,18 @@ class TestSarifFormatter: assert driver["name"] == SarifFormatter.TOOL_NAME assert driver["informationUri"] == SarifFormatter.TOOL_URL rules = driver["rules"] - assert len(rules) == 1 + assert len(rules) == 3 assert rules[0]["id"] == self.matches[0].tag assert rules[0]["name"] == self.matches[0].tag assert rules[0]["shortDescription"]["text"] == self.matches[0].message - assert rules[0]["defaultConfiguration"]["level"] == "error" + assert rules[0]["defaultConfiguration"][ + "level" + ] == SarifFormatter.get_sarif_rule_severity_level(self.matches[0].rule) assert rules[0]["help"]["text"] == self.matches[0].rule.description assert rules[0]["properties"]["tags"] == self.matches[0].rule.tags assert rules[0]["helpUri"] == self.matches[0].rule.url results = sarif["runs"][0]["results"] - assert len(results) == 2 + assert len(results) == 3 for i, result in enumerate(results): assert result["ruleId"] == self.matches[i].tag assert ( @@ -126,6 +155,9 @@ class TestSarifFormatter: "startColumn" not in result["locations"][0]["physicalLocation"]["region"] ) + assert result["level"] == SarifFormatter.get_sarif_result_severity_level( + self.matches[i], + ) assert sarif["runs"][0]["originalUriBaseIds"][SarifFormatter.BASE_URI_ID]["uri"] assert results[0]["message"]["text"] == self.matches[0].details assert results[1]["message"]["text"] == self.matches[1].message @@ -151,8 +183,8 @@ def test_sarif_parsable_ignored() -> None: @pytest.mark.parametrize( ("file", "return_code"), ( - pytest.param("examples/playbooks/valid.yml", 0), - pytest.param("playbook.yml", 2), + pytest.param("examples/playbooks/valid.yml", 0, id="0"), + pytest.param("playbook.yml", 2, id="1"), ), ) def test_sarif_file(file: str, return_code: int) -> None: @@ -168,12 +200,12 @@ def test_sarif_file(file: str, return_code: int) -> None: result = subprocess.run([*cmd, file], check=False, capture_output=True) assert result.returncode == return_code assert os.path.exists(output_file.name) # noqa: PTH110 - assert os.path.getsize(output_file.name) > 0 + assert pathlib.Path(output_file.name).stat().st_size > 0 @pytest.mark.parametrize( ("file", "return_code"), - (pytest.param("examples/playbooks/valid.yml", 0),), + (pytest.param("examples/playbooks/valid.yml", 0, id="0"),), ) def test_sarif_file_creates_it_if_none_exists(file: str, return_code: int) -> None: """Test ability to create sarif file if none exists and dump output to it (--sarif-file).""" @@ -188,5 +220,5 @@ def test_sarif_file_creates_it_if_none_exists(file: str, return_code: int) -> No result = subprocess.run([*cmd, file], check=False, capture_output=True) assert result.returncode == return_code assert os.path.exists(sarif_file_name) # noqa: PTH110 - assert os.path.getsize(sarif_file_name) > 0 + assert pathlib.Path(sarif_file_name).stat().st_size > 0 pathlib.Path.unlink(pathlib.Path(sarif_file_name)) |