Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(anta.tests): BFD test module: AntaTest.Input subclasses using common input models should have validators for their required fields. #999

Merged
merged 6 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions anta/tests/bfd.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
from __future__ import annotations

from datetime import datetime, timezone
from typing import TYPE_CHECKING, ClassVar
from typing import TYPE_CHECKING, ClassVar, TypeVar

from pydantic import Field
from pydantic import Field, field_validator

from anta.input_models.bfd import BFDPeer
from anta.models import AntaCommand, AntaTest
Expand All @@ -19,6 +19,9 @@
if TYPE_CHECKING:
from anta.models import AntaTemplate

# Using a TypeVar for the BFDPeer model since mypy thinks it's a ClassVar and not a valid type when used in field validators
T = TypeVar("T", bound=BFDPeer)


class VerifyBFDSpecificPeers(AntaTest):
"""Verifies the state of IPv4 BFD peer sessions.
Expand Down Expand Up @@ -139,6 +142,22 @@ class Input(AntaTest.Input):
BFDPeer: ClassVar[type[BFDPeer]] = BFDPeer
"""To maintain backward compatibility"""

@field_validator("bfd_peers")
@classmethod
def validate_snmp_user(cls, bfd_peers: list[T]) -> list[T]:
carl-baillargeon marked this conversation as resolved.
Show resolved Hide resolved
"""Validate that 'tx_interval', 'rx_interval' or 'multiplier' field is provided in each BFD peer."""
carl-baillargeon marked this conversation as resolved.
Show resolved Hide resolved
for peer in bfd_peers:
if peer.tx_interval is None:
msg = f"{peer}; 'tx_interval' field missing in the input"
raise ValueError(msg)
if peer.rx_interval is None:
msg = f"{peer}; 'rx_interval' field missing in the input"
raise ValueError(msg)
if peer.multiplier is None:
msg = f"{peer}; 'multiplier' field missing in the input"
raise ValueError(msg)
carl-baillargeon marked this conversation as resolved.
Show resolved Hide resolved
return bfd_peers

@AntaTest.anta_test
def test(self) -> None:
"""Main test function for VerifyBFDPeersIntervals."""
Expand Down Expand Up @@ -299,6 +318,16 @@ class Input(AntaTest.Input):
BFDPeer: ClassVar[type[BFDPeer]] = BFDPeer
"""To maintain backward compatibility"""

@field_validator("bfd_peers")
@classmethod
def validate_snmp_user(cls, bfd_peers: list[T]) -> list[T]:
"""Validate that 'protocols' field is provided in each BFD peer."""
for peer in bfd_peers:
if peer.protocols is None:
msg = f"{peer}; 'protocols' field missing in the input"
carl-baillargeon marked this conversation as resolved.
Show resolved Hide resolved
raise ValueError(msg)
return bfd_peers

@AntaTest.anta_test
def test(self) -> None:
"""Main test function for VerifyBFDPeersRegProtocols."""
Expand Down
69 changes: 69 additions & 0 deletions tests/units/input_models/test_bfd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# 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.
"""Tests for anta.input_models.bfd.py."""

# pylint: disable=C0302
carl-baillargeon marked this conversation as resolved.
Show resolved Hide resolved
from __future__ import annotations

from typing import TYPE_CHECKING

import pytest
from pydantic import ValidationError

from anta.tests.bfd import VerifyBFDPeersIntervals, VerifyBFDPeersRegProtocols

if TYPE_CHECKING:
from anta.input_models.bfd import BFDPeer


class TestVerifyBFDPeersIntervalsInput:
"""Test anta.tests.bfd.VerifyBFDPeersIntervals.Input."""

@pytest.mark.parametrize(
("bfd_peers"),
[
pytest.param([{"peer_address": "10.0.0.1", "vrf": "default", "tx_interval": 1200, "rx_interval": 1200, "multiplier": 3}], id="valid"),
],
)
def test_valid(self, bfd_peers: list[BFDPeer]) -> None:
"""Test VerifyBFDPeersIntervals.Input valid inputs."""
VerifyBFDPeersIntervals.Input(bfd_peers=bfd_peers)

@pytest.mark.parametrize(
("bfd_peers"),
[
pytest.param([{"peer_address": "10.0.0.1", "vrf": "default", "tx_interval": 1200}], id="invalid-tx-interval"),
pytest.param([{"peer_address": "10.0.0.1", "vrf": "default", "rx_interval": 1200}], id="invalid-rx-interval"),
pytest.param([{"peer_address": "10.0.0.1", "vrf": "default", "tx_interval": 1200, "rx_interval": 1200}], id="invalid-multiplier"),
],
)
def test_invalid(self, bfd_peers: list[BFDPeer]) -> None:
"""Test VerifyBFDPeersIntervals.Input invalid inputs."""
with pytest.raises(ValidationError):
VerifyBFDPeersIntervals.Input(bfd_peers=bfd_peers)


class TestVerifyBFDPeersRegProtocolsInput:
"""Test anta.tests.bfd.VerifyBFDPeersRegProtocols.Input."""

@pytest.mark.parametrize(
("bfd_peers"),
[
pytest.param([{"peer_address": "10.0.0.1", "vrf": "default", "protocols": ["bgp"]}], id="valid"),
],
)
def test_valid(self, bfd_peers: list[BFDPeer]) -> None:
"""Test VerifyBFDPeersRegProtocols.Input valid inputs."""
VerifyBFDPeersRegProtocols.Input(bfd_peers=bfd_peers)

@pytest.mark.parametrize(
("bfd_peers"),
[
pytest.param([{"peer_address": "10.0.0.1", "vrf": "default"}], id="invalid"),
],
)
def test_invalid(self, bfd_peers: list[BFDPeer]) -> None:
"""Test VerifyBFDPeersRegProtocols.Input invalid inputs."""
with pytest.raises(ValidationError):
VerifyBFDPeersRegProtocols.Input(bfd_peers=bfd_peers)
Loading