diff options
Diffstat (limited to 'test/test_runner.py')
-rw-r--r-- | test/test_runner.py | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/test/test_runner.py b/test/test_runner.py new file mode 100644 index 0000000..e89cee1 --- /dev/null +++ b/test/test_runner.py @@ -0,0 +1,210 @@ +"""Tests for runner submodule.""" +# Copyright (c) 2013-2014 Will Thames <will@thames.id.au> +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +from __future__ import annotations + +from pathlib import Path +from typing import TYPE_CHECKING, Any + +import pytest + +from ansiblelint import formatters +from ansiblelint.file_utils import Lintable +from ansiblelint.runner import Runner + +if TYPE_CHECKING: + from ansiblelint.rules import RulesCollection + +LOTS_OF_WARNINGS_PLAYBOOK = Path("examples/playbooks/lots_of_warnings.yml").resolve() + + +@pytest.mark.parametrize( + ("playbook", "exclude", "length"), + ( + pytest.param( + Path("examples/playbooks/nomatchestest.yml"), + [], + 0, + id="nomatchestest", + ), + pytest.param(Path("examples/playbooks/unicode.yml"), [], 1, id="unicode"), + pytest.param( + LOTS_OF_WARNINGS_PLAYBOOK, + [LOTS_OF_WARNINGS_PLAYBOOK], + 992, + id="lots_of_warnings", + ), + pytest.param(Path("examples/playbooks/become.yml"), [], 0, id="become"), + pytest.param( + Path("examples/playbooks/contains_secrets.yml"), + [], + 0, + id="contains_secrets", + ), + ), +) +def test_runner( + default_rules_collection: RulesCollection, + playbook: Path, + exclude: list[str], + length: int, +) -> None: + """Test that runner can go through any corner cases.""" + runner = Runner(playbook, rules=default_rules_collection, exclude_paths=exclude) + + matches = runner.run() + + assert len(matches) == length + + +def test_runner_exclude_paths(default_rules_collection: RulesCollection) -> None: + """Test that exclude paths do work.""" + runner = Runner( + "examples/playbooks/deep/", + rules=default_rules_collection, + exclude_paths=["examples/playbooks/deep/empty.yml"], + ) + + matches = runner.run() + assert len(matches) == 0 + + +@pytest.mark.parametrize(("exclude_path"), ("**/playbooks/*.yml",)) +def test_runner_exclude_globs( + default_rules_collection: RulesCollection, + exclude_path: str, +) -> None: + """Test that globs work.""" + runner = Runner( + "examples/playbooks", + rules=default_rules_collection, + exclude_paths=[exclude_path], + ) + + matches = runner.run() + # we expect to find one match from the very few .yaml file we have there (most of them have .yml extension) + assert len(matches) == 1 + + +@pytest.mark.parametrize( + ("formatter_cls"), + ( + pytest.param(formatters.Formatter, id="Formatter-plain"), + pytest.param(formatters.ParseableFormatter, id="ParseableFormatter-colored"), + pytest.param(formatters.QuietFormatter, id="QuietFormatter-colored"), + pytest.param(formatters.Formatter, id="Formatter-colored"), + ), +) +def test_runner_unicode_format( + default_rules_collection: RulesCollection, + formatter_cls: type[formatters.BaseFormatter[Any]], +) -> None: + """Check that all formatters are unicode-friendly.""" + formatter = formatter_cls(Path.cwd(), display_relative_path=True) + runner = Runner( + Lintable("examples/playbooks/unicode.yml", kind="playbook"), + rules=default_rules_collection, + ) + + matches = runner.run() + + formatter.apply(matches[0]) + + +@pytest.mark.parametrize( + "directory_name", + ( + pytest.param(Path("test/fixtures/verbosity-tests"), id="rel"), + pytest.param(Path("test/fixtures/verbosity-tests").resolve(), id="abs"), + ), +) +def test_runner_with_directory( + default_rules_collection: RulesCollection, + directory_name: Path, +) -> None: + """Check that runner detects a directory as role.""" + runner = Runner(directory_name, rules=default_rules_collection) + + expected = Lintable(name=directory_name, kind="role") + assert expected in runner.lintables + + +def test_files_not_scanned_twice(default_rules_collection: RulesCollection) -> None: + """Ensure that lintables aren't double-checked.""" + checked_files: set[Lintable] = set() + + filename = Path("examples/playbooks/common-include-1.yml").resolve() + runner = Runner( + filename, + rules=default_rules_collection, + verbosity=0, + checked_files=checked_files, + ) + run1 = runner.run() + assert len(runner.checked_files) == 2 + assert len(run1) == 1 + + filename = Path("examples/playbooks/common-include-2.yml").resolve() + runner = Runner( + str(filename), + rules=default_rules_collection, + verbosity=0, + checked_files=checked_files, + ) + run2 = runner.run() + assert len(runner.checked_files) == 3 + # this second run should return 0 because the included filed was already + # processed and added to checked_files, which acts like a bypass list. + assert len(run2) == 0 + + +def test_runner_not_found(default_rules_collection: RulesCollection) -> None: + """Ensure that lintables aren't double-checked.""" + checked_files: set[Lintable] = set() + + filename = Path("this/folder/does/not/exist").resolve() + runner = Runner( + filename, + rules=default_rules_collection, + verbosity=0, + checked_files=checked_files, + ) + result = runner.run() + assert len(runner.checked_files) == 1 + assert len(result) == 1 + assert result[0].tag == "load-failure[not-found]" + + +def test_runner_tmp_file( + tmp_path: Path, + default_rules_collection: RulesCollection, +) -> None: + """Ensure we do not ignore an explicit temporary file from linting.""" + # https://github.com/ansible/ansible-lint/issues/2628 + filename = tmp_path / "playbook.yml" + filename.write_text("---\n") + runner = Runner( + filename, + rules=default_rules_collection, + verbosity=0, + ) + result = runner.run() + assert len(result) == 1 + assert result[0].tag == "syntax-check[empty-playbook]" |