Merging upstream version 1.3.0.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-03-17 07:33:51 +01:00
parent 5b922100c9
commit 8a6a3342fc
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
337 changed files with 16571 additions and 4891 deletions

View file

@ -1,4 +1,4 @@
# Copyright (c) 2023-2024 Arista Networks, Inc.
# Copyright (c) 2023-2025 Arista Networks, Inc.
# Use of this source code is governed by the Apache License 2.0
# that can be found in the LICENSE file.
"""Test anta.result_manager.__init__.py."""
@ -20,6 +20,7 @@ if TYPE_CHECKING:
from anta.result_manager.models import TestResult
# pylint: disable=too-many-public-methods
class TestResultManager:
"""Test ResultManager class."""
@ -73,8 +74,8 @@ class TestResultManager:
assert test.get("custom_field") is None
assert test.get("result") == "success"
def test_sorted_category_stats(self, list_result_factory: Callable[[int], list[TestResult]]) -> None:
"""Test ResultManager.sorted_category_stats."""
def test_category_stats(self, list_result_factory: Callable[[int], list[TestResult]]) -> None:
"""Test ResultManager.category_stats."""
result_manager = ResultManager()
results = list_result_factory(4)
@ -86,13 +87,9 @@ class TestResultManager:
result_manager.results = results
# Check the current categories order
expected_order = ["ospf", "bgp", "vxlan", "system"]
assert list(result_manager.category_stats.keys()) == expected_order
# Check the sorted categories order
# Check that category_stats returns sorted order by default
expected_order = ["bgp", "ospf", "system", "vxlan"]
assert list(result_manager.sorted_category_stats.keys()) == expected_order
assert list(result_manager.category_stats.keys()) == expected_order
@pytest.mark.parametrize(
("starting_status", "test_status", "expected_status", "expected_raise"),
@ -198,12 +195,12 @@ class TestResultManager:
"""Test ResultManager.get_results."""
# Check for single status
success_results = result_manager.get_results(status={AntaTestStatus.SUCCESS})
assert len(success_results) == 7
assert len(success_results) == 4
assert all(r.result == "success" for r in success_results)
# Check for multiple statuses
failure_results = result_manager.get_results(status={AntaTestStatus.FAILURE, AntaTestStatus.ERROR})
assert len(failure_results) == 21
assert len(failure_results) == 17
assert all(r.result in {"failure", "error"} for r in failure_results)
# Check all results
@ -215,19 +212,18 @@ class TestResultManager:
# Check all results with sort_by result
all_results = result_manager.get_results(sort_by=["result"])
assert len(all_results) == 30
assert [r.result for r in all_results] == ["error"] * 2 + ["failure"] * 19 + ["skipped"] * 2 + ["success"] * 7
assert [r.result for r in all_results] == ["error"] * 2 + ["failure"] * 15 + ["skipped"] * 9 + ["success"] * 4
# Check all results with sort_by device (name)
all_results = result_manager.get_results(sort_by=["name"])
assert len(all_results) == 30
assert all_results[0].name == "DC1-LEAF1A"
assert all_results[-1].name == "DC1-SPINE1"
assert all_results[0].name == "s1-spine1"
# Check multiple statuses with sort_by categories
success_skipped_results = result_manager.get_results(status={AntaTestStatus.SUCCESS, AntaTestStatus.SKIPPED}, sort_by=["categories"])
assert len(success_skipped_results) == 9
assert success_skipped_results[0].categories == ["Interfaces"]
assert success_skipped_results[-1].categories == ["VXLAN"]
assert len(success_skipped_results) == 13
assert success_skipped_results[0].categories == ["avt"]
assert success_skipped_results[-1].categories == ["vxlan"]
# Check all results with bad sort_by
with pytest.raises(
@ -244,14 +240,14 @@ class TestResultManager:
assert result_manager.get_total_results() == 30
# Test single status
assert result_manager.get_total_results(status={AntaTestStatus.SUCCESS}) == 7
assert result_manager.get_total_results(status={AntaTestStatus.FAILURE}) == 19
assert result_manager.get_total_results(status={AntaTestStatus.SUCCESS}) == 4
assert result_manager.get_total_results(status={AntaTestStatus.FAILURE}) == 15
assert result_manager.get_total_results(status={AntaTestStatus.ERROR}) == 2
assert result_manager.get_total_results(status={AntaTestStatus.SKIPPED}) == 2
assert result_manager.get_total_results(status={AntaTestStatus.SKIPPED}) == 9
# Test multiple statuses
assert result_manager.get_total_results(status={AntaTestStatus.SUCCESS, AntaTestStatus.FAILURE}) == 26
assert result_manager.get_total_results(status={AntaTestStatus.SUCCESS, AntaTestStatus.FAILURE, AntaTestStatus.ERROR}) == 28
assert result_manager.get_total_results(status={AntaTestStatus.SUCCESS, AntaTestStatus.FAILURE}) == 19
assert result_manager.get_total_results(status={AntaTestStatus.SUCCESS, AntaTestStatus.FAILURE, AntaTestStatus.ERROR}) == 21
assert result_manager.get_total_results(status={AntaTestStatus.SUCCESS, AntaTestStatus.FAILURE, AntaTestStatus.ERROR, AntaTestStatus.SKIPPED}) == 30
@pytest.mark.parametrize(
@ -465,7 +461,6 @@ class TestResultManager:
with caplog.at_level(logging.INFO):
_ = result_manager.category_stats
_ = result_manager.test_stats
_ = result_manager.sorted_category_stats
assert "Computing statistics" not in caplog.text
# Add another result - should mark stats as unsynced
@ -480,3 +475,89 @@ class TestResultManager:
_ = result_manager.device_stats
assert "Computing statistics for all results" in caplog.text
assert result_manager._stats_in_sync is True
def test_sort_by_result(self, test_result_factory: Callable[[], TestResult]) -> None:
"""Test sorting by result."""
result_manager = ResultManager()
test1 = test_result_factory()
test1.result = AntaTestStatus.SUCCESS
test2 = test_result_factory()
test2.result = AntaTestStatus.FAILURE
test3 = test_result_factory()
test3.result = AntaTestStatus.ERROR
result_manager.results = [test1, test2, test3]
sorted_manager = result_manager.sort(["result"])
assert [r.result for r in sorted_manager.results] == ["error", "failure", "success"]
def test_sort_by_name(self, test_result_factory: Callable[[], TestResult]) -> None:
"""Test sorting by name."""
result_manager = ResultManager()
test1 = test_result_factory()
test1.name = "Device3"
test2 = test_result_factory()
test2.name = "Device1"
test3 = test_result_factory()
test3.name = "Device2"
result_manager.results = [test1, test2, test3]
sorted_manager = result_manager.sort(["name"])
assert [r.name for r in sorted_manager.results] == ["Device1", "Device2", "Device3"]
def test_sort_by_categories(self, test_result_factory: Callable[[], TestResult]) -> None:
"""Test sorting by categories."""
result_manager = ResultManager()
test1 = test_result_factory()
test1.categories = ["VXLAN", "networking"]
test2 = test_result_factory()
test2.categories = ["BGP", "routing"]
test3 = test_result_factory()
test3.categories = ["system", "hardware"]
result_manager.results = [test1, test2, test3]
sorted_manager = result_manager.sort(["categories"])
results = sorted_manager.results
assert results[0].categories == ["BGP", "routing"]
assert results[1].categories == ["VXLAN", "networking"]
assert results[2].categories == ["system", "hardware"]
def test_sort_multiple_fields(self, test_result_factory: Callable[[], TestResult]) -> None:
"""Test sorting by multiple fields."""
result_manager = ResultManager()
test1 = test_result_factory()
test1.result = AntaTestStatus.ERROR
test1.test = "Test3"
test2 = test_result_factory()
test2.result = AntaTestStatus.ERROR
test2.test = "Test1"
test3 = test_result_factory()
test3.result = AntaTestStatus.FAILURE
test3.test = "Test2"
result_manager.results = [test1, test2, test3]
sorted_manager = result_manager.sort(["result", "test"])
results = sorted_manager.results
assert results[0].result == "error"
assert results[0].test == "Test1"
assert results[1].result == "error"
assert results[1].test == "Test3"
assert results[2].result == "failure"
assert results[2].test == "Test2"
def test_sort_invalid_field(self) -> None:
"""Test that sort method raises ValueError for invalid sort_by fields."""
result_manager = ResultManager()
with pytest.raises(
ValueError,
match=re.escape(
"Invalid sort_by fields: ['bad_field']. Accepted fields are: ['name', 'test', 'categories', 'description', 'result', 'messages', 'custom_field']",
),
):
result_manager.sort(["bad_field"])
def test_sort_is_chainable(self) -> None:
"""Test that the sort method is chainable."""
result_manager = ResultManager()
assert isinstance(result_manager.sort(["name"]), ResultManager)