diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:06:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:06:49 +0000 |
commit | 2fe34b6444502079dc0b84365ce82dbc92de308e (patch) | |
tree | 8fedcab52bbbc3db6c5aa909a88a7a7b81685018 /test/test_formatter_sarif.py | |
parent | Initial commit. (diff) | |
download | ansible-lint-1f847810e1dcffeab102ff853e50a09833fad025.tar.xz ansible-lint-1f847810e1dcffeab102ff853e50a09833fad025.zip |
Adding upstream version 6.17.2.upstream/6.17.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'test/test_formatter_sarif.py')
-rw-r--r-- | test/test_formatter_sarif.py | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/test/test_formatter_sarif.py b/test/test_formatter_sarif.py new file mode 100644 index 0000000..026d336 --- /dev/null +++ b/test/test_formatter_sarif.py @@ -0,0 +1,192 @@ +"""Test the codeclimate JSON formatter.""" +from __future__ import annotations + +import json +import os +import pathlib +import subprocess +import sys +from tempfile import NamedTemporaryFile + +import pytest + +from ansiblelint.errors import MatchError +from ansiblelint.file_utils import Lintable +from ansiblelint.formatters import SarifFormatter +from ansiblelint.rules import AnsibleLintRule + + +class TestSarifFormatter: + """Unit test for SarifFormatter.""" + + rule = AnsibleLintRule() + matches: list[MatchError] = [] + formatter: SarifFormatter | None = None + + 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.formatter = SarifFormatter(pathlib.Path.cwd(), display_relative_path=True) + + def test_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: + """Test if returned string value is a JSON.""" + assert isinstance(self.formatter, SarifFormatter) + output = self.formatter.format_result(self.matches) + json.loads(output) + # https://github.com/ansible/ansible-navigator/issues/1490 + assert "\n" not in output + + def test_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): + 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.""" + assert isinstance(self.formatter, SarifFormatter) + sarif = json.loads(self.formatter.format_result(self.matches)) + assert len(sarif["runs"][0]["results"]) == 2 + + def test_validate_sarif_schema(self) -> None: + """Test if the returned JSON is a valid SARIF report.""" + assert isinstance(self.formatter, SarifFormatter) + sarif = json.loads(self.formatter.format_result(self.matches)) + assert sarif["$schema"] == SarifFormatter.SARIF_SCHEMA + assert sarif["version"] == SarifFormatter.SARIF_SCHEMA_VERSION + driver = sarif["runs"][0]["tool"]["driver"] + assert driver["name"] == SarifFormatter.TOOL_NAME + assert driver["informationUri"] == SarifFormatter.TOOL_URL + rules = driver["rules"] + assert len(rules) == 1 + 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]["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 + for i, result in enumerate(results): + assert result["ruleId"] == self.matches[i].tag + assert ( + result["locations"][0]["physicalLocation"]["artifactLocation"]["uri"] + == self.matches[i].filename + ) + assert ( + result["locations"][0]["physicalLocation"]["artifactLocation"][ + "uriBaseId" + ] + == SarifFormatter.BASE_URI_ID + ) + assert ( + result["locations"][0]["physicalLocation"]["region"]["startLine"] + == self.matches[i].lineno + ) + if self.matches[i].column: + assert ( + result["locations"][0]["physicalLocation"]["region"]["startColumn"] + == self.matches[i].column + ) + else: + assert ( + "startColumn" + not in result["locations"][0]["physicalLocation"]["region"] + ) + 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 + + +def test_sarif_parsable_ignored() -> None: + """Test that -p option does not alter SARIF format.""" + cmd = [ + sys.executable, + "-m", + "ansiblelint", + "-v", + "-p", + ] + file = "examples/playbooks/empty_playbook.yml" + result = subprocess.run([*cmd, file], check=False) + result2 = subprocess.run([*cmd, "-p", file], check=False) + + assert result.returncode == result2.returncode + assert result.stdout == result2.stdout + + +@pytest.mark.parametrize( + ("file", "return_code"), + ( + pytest.param("examples/playbooks/valid.yml", 0), + pytest.param("playbook.yml", 2), + ), +) +def test_sarif_file(file: str, return_code: int) -> None: + """Test ability to dump sarif file (--sarif-file).""" + with NamedTemporaryFile(mode="w", suffix=".sarif", prefix="output") as output_file: + cmd = [ + sys.executable, + "-m", + "ansiblelint", + "--sarif-file", + str(output_file.name), + ] + 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 + + +@pytest.mark.parametrize( + ("file", "return_code"), + (pytest.param("examples/playbooks/valid.yml", 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).""" + sarif_file_name = "test_output.sarif" + cmd = [ + sys.executable, + "-m", + "ansiblelint", + "--sarif-file", + sarif_file_name, + ] + 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 + pathlib.Path.unlink(pathlib.Path(sarif_file_name)) |