summaryrefslogtreecommitdiffstats
path: root/tests/units/test_custom_types.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/units/test_custom_types.py')
-rw-r--r--tests/units/test_custom_types.py264
1 files changed, 264 insertions, 0 deletions
diff --git a/tests/units/test_custom_types.py b/tests/units/test_custom_types.py
new file mode 100644
index 0000000..8119849
--- /dev/null
+++ b/tests/units/test_custom_types.py
@@ -0,0 +1,264 @@
+# Copyright (c) 2023-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.
+"""Tests for `anta.custom_types`.
+
+The intention is only to test here what is not used already in other places.
+
+TODO: Expand later.
+"""
+
+from __future__ import annotations
+
+import re
+
+import pytest
+
+from anta.custom_types import (
+ REGEX_BGP_IPV4_MPLS_VPN,
+ REGEX_BGP_IPV4_UNICAST,
+ REGEXP_BGP_IPV4_MPLS_LABELS,
+ REGEXP_BGP_L2VPN_AFI,
+ REGEXP_EOS_BLACKLIST_CMDS,
+ REGEXP_INTERFACE_ID,
+ REGEXP_PATH_MARKERS,
+ REGEXP_TYPE_EOS_INTERFACE,
+ REGEXP_TYPE_HOSTNAME,
+ REGEXP_TYPE_VXLAN_SRC_INTERFACE,
+ aaa_group_prefix,
+ bgp_multiprotocol_capabilities_abbreviations,
+ interface_autocomplete,
+ interface_case_sensitivity,
+)
+
+# ------------------------------------------------------------------------------
+# TEST custom_types.py regular expressions
+# ------------------------------------------------------------------------------
+
+
+def test_regexp_path_markers() -> None:
+ """Test REGEXP_PATH_MARKERS."""
+ # Test strings that should match the pattern
+ assert re.search(REGEXP_PATH_MARKERS, "show/bgp/interfaces") is not None
+ assert re.search(REGEXP_PATH_MARKERS, "show\\bgp") is not None
+ assert re.search(REGEXP_PATH_MARKERS, "show bgp") is not None
+
+ # Test strings that should not match the pattern
+ assert re.search(REGEXP_PATH_MARKERS, "aaaa") is None
+ assert re.search(REGEXP_PATH_MARKERS, "11111") is None
+ assert re.search(REGEXP_PATH_MARKERS, ".[]?<>") is None
+
+
+def test_regexp_bgp_l2vpn_afi() -> None:
+ """Test REGEXP_BGP_L2VPN_AFI."""
+ # Test strings that should match the pattern
+ assert re.search(REGEXP_BGP_L2VPN_AFI, "l2vpn-evpn") is not None
+ assert re.search(REGEXP_BGP_L2VPN_AFI, "l2 vpn evpn") is not None
+ assert re.search(REGEXP_BGP_L2VPN_AFI, "l2-vpn evpn") is not None
+ assert re.search(REGEXP_BGP_L2VPN_AFI, "l2vpn evpn") is not None
+ assert re.search(REGEXP_BGP_L2VPN_AFI, "l2vpnevpn") is not None
+ assert re.search(REGEXP_BGP_L2VPN_AFI, "l2 vpnevpn") is not None
+
+ # Test strings that should not match the pattern
+ assert re.search(REGEXP_BGP_L2VPN_AFI, "al2vpn evpn") is None
+ assert re.search(REGEXP_BGP_L2VPN_AFI, "l2vpn-evpna") is None
+
+
+def test_regexp_bgp_ipv4_mpls_labels() -> None:
+ """Test REGEXP_BGP_IPV4_MPLS_LABELS."""
+ assert re.search(REGEXP_BGP_IPV4_MPLS_LABELS, "ipv4-mpls-label") is not None
+ assert re.search(REGEXP_BGP_IPV4_MPLS_LABELS, "ipv4 mpls labels") is not None
+ assert re.search(REGEXP_BGP_IPV4_MPLS_LABELS, "ipv4Mplslabel") is None
+
+
+def test_regex_bgp_ipv4_mpls_vpn() -> None:
+ """Test REGEX_BGP_IPV4_MPLS_VPN."""
+ assert re.search(REGEX_BGP_IPV4_MPLS_VPN, "ipv4-mpls-vpn") is not None
+ assert re.search(REGEX_BGP_IPV4_MPLS_VPN, "ipv4_mplsvpn") is None
+
+
+def test_regex_bgp_ipv4_unicast() -> None:
+ """Test REGEX_BGP_IPV4_UNICAST."""
+ assert re.search(REGEX_BGP_IPV4_UNICAST, "ipv4-uni-cast") is not None
+ assert re.search(REGEX_BGP_IPV4_UNICAST, "ipv4+unicast") is None
+
+
+def test_regexp_type_interface_id() -> None:
+ """Test REGEXP_INTERFACE_ID."""
+ intf_id_re = re.compile(f"{REGEXP_INTERFACE_ID}")
+
+ # Test strings that should match the pattern
+ assert intf_id_re.search("123") is not None
+ assert intf_id_re.search("123/456") is not None
+ assert intf_id_re.search("123.456") is not None
+ assert intf_id_re.search("123/456.789") is not None
+
+
+def test_regexp_type_eos_interface() -> None:
+ """Test REGEXP_TYPE_EOS_INTERFACE."""
+ # Test strings that should match the pattern
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Ethernet0") is not None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Vlan100") is not None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Port-Channel1/0") is not None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Loopback0.1") is not None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Management0/0/0") is not None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Tunnel1") is not None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Vxlan1") is not None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Fabric1") is not None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Dps1") is not None
+
+ # Test strings that should not match the pattern
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Ethernet") is None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Vlan") is None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Port-Channel") is None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Loopback.") is None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Management/") is None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Tunnel") is None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Vxlan") is None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Fabric") is None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Dps") is None
+
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Ethernet1/a") is None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Port-Channel-100") is None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Loopback.10") is None
+ assert re.match(REGEXP_TYPE_EOS_INTERFACE, "Management/10") is None
+
+
+def test_regexp_type_vxlan_src_interface() -> None:
+ """Test REGEXP_TYPE_VXLAN_SRC_INTERFACE."""
+ # Test strings that should match the pattern
+ assert re.match(REGEXP_TYPE_VXLAN_SRC_INTERFACE, "Loopback0") is not None
+ assert re.match(REGEXP_TYPE_VXLAN_SRC_INTERFACE, "Loopback1") is not None
+ assert re.match(REGEXP_TYPE_VXLAN_SRC_INTERFACE, "Loopback99") is not None
+ assert re.match(REGEXP_TYPE_VXLAN_SRC_INTERFACE, "Loopback100") is not None
+ assert re.match(REGEXP_TYPE_VXLAN_SRC_INTERFACE, "Loopback8190") is not None
+ assert re.match(REGEXP_TYPE_VXLAN_SRC_INTERFACE, "Loopback8199") is not None
+
+ # Test strings that should not match the pattern
+ assert re.match(REGEXP_TYPE_VXLAN_SRC_INTERFACE, "Loopback") is None
+ assert re.match(REGEXP_TYPE_VXLAN_SRC_INTERFACE, "Loopback9001") is None
+ assert re.match(REGEXP_TYPE_VXLAN_SRC_INTERFACE, "Loopback9000") is None
+
+
+def test_regexp_type_hostname() -> None:
+ """Test REGEXP_TYPE_HOSTNAME."""
+ # Test strings that should match the pattern
+ assert re.match(REGEXP_TYPE_HOSTNAME, "hostname") is not None
+ assert re.match(REGEXP_TYPE_HOSTNAME, "hostname.com") is not None
+ assert re.match(REGEXP_TYPE_HOSTNAME, "host-name.com") is not None
+ assert re.match(REGEXP_TYPE_HOSTNAME, "host.name.com") is not None
+ assert re.match(REGEXP_TYPE_HOSTNAME, "host-name1.com") is not None
+
+ # Test strings that should not match the pattern
+ assert re.match(REGEXP_TYPE_HOSTNAME, "-hostname.com") is None
+ assert re.match(REGEXP_TYPE_HOSTNAME, ".hostname.com") is None
+ assert re.match(REGEXP_TYPE_HOSTNAME, "hostname-.com") is None
+ assert re.match(REGEXP_TYPE_HOSTNAME, "hostname..com") is None
+
+
+@pytest.mark.parametrize(
+ ("test_string", "expected"),
+ [
+ ("reload", True), # matches "^reload.*"
+ ("reload now", True), # matches "^reload.*"
+ ("configure terminal", True), # matches "^conf\w*\s*(terminal|session)*"
+ ("conf t", True), # matches "^conf\w*\s*(terminal|session)*"
+ ("write memory", True), # matches "^wr\w*\s*\w+"
+ ("wr mem", True), # matches "^wr\w*\s*\w+"
+ ("show running-config", False), # does not match any regex
+ ("no shutdown", False), # does not match any regex
+ ("", False), # empty string does not match any regex
+ ],
+)
+def test_regexp_eos_blacklist_cmds(test_string: str, expected: bool) -> None:
+ """Test REGEXP_EOS_BLACKLIST_CMDS."""
+
+ def matches_any_regex(string: str, regex_list: list[str]) -> bool:
+ """
+ Check if a string matches at least one regular expression in a list.
+
+ :param string: The string to check.
+ :param regex_list: A list of regular expressions.
+ :return: True if the string matches at least one regular expression, False otherwise.
+ """
+ return any(re.match(regex, string) for regex in regex_list)
+
+ assert matches_any_regex(test_string, REGEXP_EOS_BLACKLIST_CMDS) == expected
+
+
+# ------------------------------------------------------------------------------
+# TEST custom_types.py functions
+# ------------------------------------------------------------------------------
+
+
+def test_interface_autocomplete_success() -> None:
+ """Test interface_autocomplete with valid inputs."""
+ assert interface_autocomplete("et1") == "Ethernet1"
+ assert interface_autocomplete("et1/1") == "Ethernet1/1"
+ assert interface_autocomplete("et1.1") == "Ethernet1.1"
+ assert interface_autocomplete("et1/1.1") == "Ethernet1/1.1"
+ assert interface_autocomplete("eth2") == "Ethernet2"
+ assert interface_autocomplete("po3") == "Port-Channel3"
+ assert interface_autocomplete("lo4") == "Loopback4"
+
+
+def test_interface_autocomplete_no_alias() -> None:
+ """Test interface_autocomplete with inputs that don't have aliases."""
+ assert interface_autocomplete("GigabitEthernet1") == "GigabitEthernet1"
+ assert interface_autocomplete("Vlan10") == "Vlan10"
+ assert interface_autocomplete("Tunnel100") == "Tunnel100"
+
+
+def test_interface_autocomplete_failure() -> None:
+ """Trigger ValueError for interface_autocomplete."""
+ with pytest.raises(ValueError, match="Could not parse interface ID in interface"):
+ interface_autocomplete("ThisIsNotAnInterface")
+
+
+@pytest.mark.parametrize(
+ ("str_input", "expected_output"),
+ [
+ pytest.param("L2VPNEVPN", "l2VpnEvpn", id="l2VpnEvpn"),
+ pytest.param("ipv4-mplsLabels", "ipv4MplsLabels", id="ipv4MplsLabels"),
+ pytest.param("ipv4-mpls-vpn", "ipv4MplsVpn", id="ipv4MplsVpn"),
+ pytest.param("ipv4-unicast", "ipv4Unicast", id="ipv4Unicast"),
+ pytest.param("BLAH", "BLAH", id="unmatched"),
+ ],
+)
+def test_bgp_multiprotocol_capabilities_abbreviationsh(str_input: str, expected_output: str) -> None:
+ """Test bgp_multiprotocol_capabilities_abbreviations."""
+ assert bgp_multiprotocol_capabilities_abbreviations(str_input) == expected_output
+
+
+def test_aaa_group_prefix_known_method() -> None:
+ """Test aaa_group_prefix with a known method."""
+ assert aaa_group_prefix("local") == "local"
+ assert aaa_group_prefix("none") == "none"
+ assert aaa_group_prefix("logging") == "logging"
+
+
+def test_aaa_group_prefix_unknown_method() -> None:
+ """Test aaa_group_prefix with an unknown method."""
+ assert aaa_group_prefix("demo") == "group demo"
+ assert aaa_group_prefix("group1") == "group group1"
+
+
+def test_interface_case_sensitivity_lowercase() -> None:
+ """Test interface_case_sensitivity with lowercase inputs."""
+ assert interface_case_sensitivity("ethernet") == "Ethernet"
+ assert interface_case_sensitivity("vlan") == "Vlan"
+ assert interface_case_sensitivity("loopback") == "Loopback"
+
+
+def test_interface_case_sensitivity_mixed_case() -> None:
+ """Test interface_case_sensitivity with mixed case inputs."""
+ assert interface_case_sensitivity("Ethernet") == "Ethernet"
+ assert interface_case_sensitivity("Vlan") == "Vlan"
+ assert interface_case_sensitivity("Loopback") == "Loopback"
+
+
+def test_interface_case_sensitivity_uppercase() -> None:
+ """Test interface_case_sensitivity with uppercase inputs."""
+ assert interface_case_sensitivity("ETHERNET") == "ETHERNET"
+ assert interface_case_sensitivity("VLAN") == "VLAN"
+ assert interface_case_sensitivity("LOOPBACK") == "LOOPBACK"