Adding upstream version 1.2.0.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-05 11:55:09 +01:00
parent 77504588ab
commit 6fd6eb426a
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
154 changed files with 7346 additions and 5000 deletions

View file

@ -0,0 +1,4 @@
# Copyright (c) 2024 Arista Networks, Inc.
# Use of this source code is governed by the Apache License 2.0
# that can be found in the LICENSE file.
"""Module used for test purposes."""

View file

@ -114,6 +114,27 @@ def test_from_cvp(
assert result.exit_code == ExitCode.OK
def test_from_cvp_os_error(tmp_path: Path, click_runner: CliRunner, caplog: pytest.LogCaptureFixture) -> None:
"""Test from_cvp when an OSError occurs."""
output: Path = tmp_path / "output.yml"
cli_args = ["get", "from-cvp", "--output", str(output), "--host", "42.42.42.42", "--username", "anta", "--password", "anta"]
with (
patch("anta.cli.get.commands.get_cv_token", autospec=True, side_effect=None),
patch("cvprac.cvp_client.CvpClient.connect", autospec=True, side_effect=None) as mocked_cvp_connect,
patch("cvprac.cvp_client.CvpApi.get_inventory", autospec=True, return_value=[]) as mocked_get_inventory,
patch("cvprac.cvp_client.CvpApi.get_devices_in_container", autospec=True, return_value=[]),
patch("anta.cli.get.utils.Path.open", side_effect=OSError("Permission denied")),
):
result = click_runner.invoke(anta, cli_args)
mocked_cvp_connect.assert_called_once()
mocked_get_inventory.assert_called_once()
assert not output.exists()
assert "Could not write inventory to path" in caplog.text
assert result.exit_code == ExitCode.USAGE_ERROR
@pytest.mark.parametrize(
("ansible_inventory", "ansible_group", "expected_exit", "expected_log"),
[
@ -257,8 +278,7 @@ def test_from_ansible_overwrite(
else:
temp_env["ANTA_INVENTORY"] = None
tmp_inv = tmp_output
cli_args.extend(["--output", str(tmp_output)])
cli_args.extend(["--output", str(tmp_inv)])
if overwrite:
cli_args.append("--overwrite")
@ -275,3 +295,162 @@ def test_from_ansible_overwrite(
elif expected_exit == ExitCode.INTERNAL_ERROR:
assert expected_log
assert expected_log in result.output
@pytest.mark.parametrize(
("module", "test_name", "short", "count", "expected_output", "expected_exit_code"),
[
pytest.param(
None,
None,
False,
False,
"VerifyAcctConsoleMethods",
ExitCode.OK,
id="Get all tests",
),
pytest.param(
"anta.tests.aaa",
None,
False,
False,
"VerifyAcctConsoleMethods",
ExitCode.OK,
id="Get tests, filter on module",
),
pytest.param(
None,
"VerifyNTPAssociations",
False,
False,
"VerifyNTPAssociations",
ExitCode.OK,
id="Get tests, filter on exact test name",
),
pytest.param(
None,
"VerifyNTP",
False,
False,
"anta.tests.system",
ExitCode.OK,
id="Get tests, filter on included test name",
),
pytest.param(
None,
"VerifyNTP",
True,
False,
"VerifyNTPAssociations",
ExitCode.OK,
id="Get tests --short",
),
pytest.param(
"unknown_module",
None,
True,
False,
"Module `unknown_module` was not found!",
ExitCode.USAGE_ERROR,
id="Get tests wrong module",
),
pytest.param(
"unknown_module.unknown",
None,
True,
False,
"Module `unknown_module.unknown` was not found!",
ExitCode.USAGE_ERROR,
id="Get tests wrong submodule",
),
pytest.param(
".unknown_module",
None,
True,
False,
"`anta get tests --module <module>` does not support relative imports",
ExitCode.USAGE_ERROR,
id="Use relative module name",
),
pytest.param(
None,
"VerifySomething",
True,
False,
"No test 'VerifySomething' found in 'anta.tests'",
ExitCode.OK,
id="Get tests wrong test name",
),
pytest.param(
"anta.tests.aaa",
"VerifyNTP",
True,
False,
"No test 'VerifyNTP' found in 'anta.tests.aaa'",
ExitCode.OK,
id="Get tests test exists but not in module",
),
pytest.param(
"anta.tests.system",
"VerifyNTPAssociations",
False,
True,
"There is 1 test available in 'anta.tests.system'.",
ExitCode.OK,
id="Get single test count",
),
pytest.param(
"anta.tests.stun",
None,
False,
True,
"There are 3 tests available in 'anta.tests.stun'",
ExitCode.OK,
id="Get multiple test count",
),
],
)
def test_get_tests(
click_runner: CliRunner, module: str | None, test_name: str | None, *, short: bool, count: bool, expected_output: str, expected_exit_code: str
) -> None:
"""Test `anta get tests`."""
cli_args = [
"get",
"tests",
]
if module is not None:
cli_args.extend(["--module", module])
if test_name is not None:
cli_args.extend(["--test", test_name])
if short:
cli_args.append("--short")
if count:
cli_args.append("--count")
result = click_runner.invoke(anta, cli_args)
assert result.exit_code == expected_exit_code
assert expected_output in result.output
def test_get_tests_local_module(click_runner: CliRunner) -> None:
"""Test injecting CWD in sys.
The test overwrite CWD to return this file parents and local_module is located there.
"""
cli_args = ["get", "tests", "--module", "local_module"]
cwd = Path.cwd()
local_module_parent_path = Path(__file__).parent
with patch("anta.cli.get.utils.Path.cwd", return_value=local_module_parent_path):
result = click_runner.invoke(anta, cli_args)
assert result.exit_code == ExitCode.OK
# In the rare case where people would be running `pytest .` in this directory
if cwd != local_module_parent_path:
assert "injecting CWD in PYTHONPATH and retrying..." in result.output
assert "No test found in 'local_module'" in result.output

View file

@ -7,14 +7,15 @@ from __future__ import annotations
from contextlib import AbstractContextManager, nullcontext
from pathlib import Path
from typing import Any
from typing import Any, ClassVar
from unittest.mock import MagicMock, patch
import pytest
import requests
from anta.cli.get.utils import create_inventory_from_ansible, create_inventory_from_cvp, get_cv_token
from anta.cli.get.utils import create_inventory_from_ansible, create_inventory_from_cvp, extract_examples, find_tests_examples, get_cv_token, print_test
from anta.inventory import AntaInventory
from anta.models import AntaCommand, AntaTemplate, AntaTest
DATA_DIR: Path = Path(__file__).parents[3].resolve() / "data"
@ -160,3 +161,91 @@ def test_create_inventory_from_ansible(
assert not target_file.exists()
if expected_log:
assert expected_log in caplog.text
class MissingExampleTest(AntaTest):
"""ANTA test that always succeed but has no Examples section."""
categories: ClassVar[list[str]] = []
commands: ClassVar[list[AntaCommand | AntaTemplate]] = []
@AntaTest.anta_test
def test(self) -> None:
"""Test function."""
self.result.is_success()
class EmptyExampleTest(AntaTest):
"""ANTA test that always succeed but has an empty Examples section.
Examples
--------
"""
# For the test purpose we want am empty section as custom tests could not be using ruff.
# ruff: noqa: D414
categories: ClassVar[list[str]] = []
commands: ClassVar[list[AntaCommand | AntaTemplate]] = []
@AntaTest.anta_test
def test(self) -> None:
"""Test function."""
self.result.is_success()
class TypoExampleTest(AntaTest):
"""ANTA test that always succeed but has a Typo in the test name in the example.
Notice capital P in TyPo below.
Examples
--------
```yaml
tests.units.cli.get.test_utils:
- TyPoExampleTest:
```
"""
# For the test purpose we want am empty section as custom tests could not be using ruff.
# ruff: noqa: D414
categories: ClassVar[list[str]] = []
commands: ClassVar[list[AntaCommand | AntaTemplate]] = []
@AntaTest.anta_test
def test(self) -> None:
"""Test function."""
self.result.is_success()
def test_find_tests_examples() -> None:
"""Test find_tests_examples.
Only testing the failure scenarii not tested through test_commands.
TODO: expand
"""
with pytest.raises(ValueError, match="Error when importing"):
find_tests_examples("blah", "UnusedTestName")
def test_print_test() -> None:
"""Test print_test."""
with pytest.raises(ValueError, match="Could not find the name of the test"):
print_test(TypoExampleTest)
with pytest.raises(LookupError, match="is missing an Example"):
print_test(MissingExampleTest)
with pytest.raises(LookupError, match="is missing an Example"):
print_test(EmptyExampleTest)
def test_extract_examples() -> None:
"""Test extract_examples.
Only testing the case where the 'Examples' is missing as everything else
is covered already in test_commands.py.
"""
assert MissingExampleTest.__doc__ is not None
assert EmptyExampleTest.__doc__ is not None
assert extract_examples(MissingExampleTest.__doc__) is None
assert extract_examples(EmptyExampleTest.__doc__) is None