Repository: aristanetworks/anta (python)

Issue:
MultiProtocolCaps custom type should be more restrictive
Even though `MultiProtocolCaps` has support for abbreviations (IPv4 Unicast, etc.), it supports any string today:
```yaml
anta.tests.routing:
  bgp:
    - VerifyBGPPeerMPCaps:
        bgp_peers:
          - peer_address: 10.1.254.21
            vrf: default
            strict: False
            capabilities:
              - ipv4Unicast
              - pizza
```
Result:
`DC1-LEAF1A :: VerifyBGPPeerMPCaps :: FAILURE(Peer: 10.1.254.21 VRF: default - pizza not found)`

The custom type should be updated to support the following mapping (both formats):
```
MP_CAPABILITIES_MAPPING = {
   # Human readable format -> EOS format
   "Dynamic Path Selection": "dps",
   "IPv4 Unicast": "ipv4Unicast",
   "IPv6 Unicast": "ipv6Unicast",
   "IPv4 Multicast": "ipv4Multicast",
   "IPv6 Multicast": "ipv6Multicast",
   "IPv4 Labeled Unicast": "ipv4MplsLabels",
   "IPv6 Labeled Unicast": "ipv6MplsLabels",
   "IPv4 SR-TE": "ipv4SrTe",
   "IPv6 SR-TE": "ipv6SrTe",
   "IPv4 MPLS Label": "ipv4MplsVpn",
   "IPv6 MPLS Label": "ipv6MplsVpn", 
   "IPv4 Flowspec": "ipv4FlowSpec",
   "IPv6 Flowspec": "ipv6FlowSpec",
   "IPv4 Flowspec VPN": "ipv4FlowSpecVpn",
   "IPv6 Flowspec VPN": "ipv6FlowSpecVpn",
   "L2VPN VPLS": "l2VpnVpls",
   "L2VPN EVPN": "l2VpnEvpn",
   "Link State": "linkState",
   "RT Membership": "rtMembership",
   "IPv4 RtMembership": "rtMembership",
   "IPv4 MVPN": "ipv4Mvpn",
}
```



Pull request description:
refactor(anta): Update MultiProtocolCaps custom type to make it more restrictive
# Description
Updated MultiProtocolCaps custom type to make it more restrictive


Fixes #1015 
#### Note: Added codespell ignore in the custom_types.py file, to avoid the spelling check in regex pattern
# Checklist:
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have run pre-commit for code linting and typing (`pre-commit run`)
- [ ] I have made corresponding changes to the documentation
- [x] I have added tests that prove my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes (`tox -e testenv`)


Patch:
diff --git a/anta/custom_types.py b/anta/custom_types.py
index 8ca3c1c2..67646f6e 100644
--- a/anta/custom_types.py
+++ b/anta/custom_types.py
@@ -23,16 +23,6 @@ REGEX_TYPE_PORTCHANNEL = r"^Port-Channel[0-9]{1,6}$"
 REGEXP_TYPE_HOSTNAME = r"^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$"
 """Match hostname like `my-hostname`, `my-hostname-1`, `my-hostname-1-2`."""
 
-# Regexp BGP AFI/SAFI
-REGEXP_BGP_L2VPN_AFI = r"\b(l2[\s\-]?vpn[\s\-]?evpn)\b"
-"""Match L2VPN EVPN AFI."""
-REGEXP_BGP_IPV4_MPLS_LABELS = r"\b(ipv4[\s\-]?mpls[\s\-]?label(s)?)\b"
-"""Match IPv4 MPLS Labels."""
-REGEX_BGP_IPV4_MPLS_VPN = r"\b(ipv4[\s\-]?mpls[\s\-]?vpn)\b"
-"""Match IPv4 MPLS VPN."""
-REGEX_BGP_IPV4_UNICAST = r"\b(ipv4[\s\-]?uni[\s\-]?cast)\b"
-"""Match IPv4 Unicast."""
-
 
 def aaa_group_prefix(v: str) -> str:
     """Prefix the AAA method with 'group' if it is known."""
@@ -78,26 +68,57 @@ def interface_case_sensitivity(v: str) -> str:
 def bgp_multiprotocol_capabilities_abbreviations(value: str) -> str:
     """Abbreviations for different BGP multiprotocol capabilities.
 
+    Handles different separators (hyphen, underscore, space) and case sensitivity.
+
     Examples
     --------
-    - IPv4 Unicast
-    - L2vpnEVPN
-    - ipv4 MPLS Labels
-    - ipv4Mplsvpn
-
+    ```python
+    >>> bgp_multiprotocol_capabilities_abbreviations("IPv4 Unicast")
+    'ipv4Unicast'
+    >>> bgp_multiprotocol_capabilities_abbreviations("ipv4-Flow_Spec Vpn")
+    'ipv4FlowSpecVpn'
+     >>> bgp_multiprotocol_capabilities_abbreviations("ipv6_labeled-unicast")
+    'ipv6MplsLabels'
+     >>> bgp_multiprotocol_capabilities_abbreviations("ipv4_mpls_vpn")
+    'ipv4MplsVpn'
+     >>> bgp_multiprotocol_capabilities_abbreviations("ipv4 mpls labels")
+    'ipv4MplsLabels'
+    >>> bgp_multiprotocol_capabilities_abbreviations("rt-membership")
+    'rtMembership'
+     >>> bgp_multiprotocol_capabilities_abbreviations("dynamic-path-selection")
+    'dps'
+    ```
     """
     patterns = {
-        REGEXP_BGP_L2VPN_AFI: "l2VpnEvpn",
-        REGEXP_BGP_IPV4_MPLS_LABELS: "ipv4MplsLabels",
-        REGEX_BGP_IPV4_MPLS_VPN: "ipv4MplsVpn",
-        REGEX_BGP_IPV4_UNICAST: "ipv4Unicast",
+        f"{r'dynamic[-_ ]?path[-_ ]?selection$'}": "dps",
+        f"{r'dps$'}": "dps",
+        f"{r'ipv4[-_ ]?unicast$'}": "ipv4Unicast",
+        f"{r'ipv6[-_ ]?unicast$'}": "ipv6Unicast",
+        f"{r'ipv4[-_ ]?multicast$'}": "ipv4Multicast",
+        f"{r'ipv6[-_ ]?multicast$'}": "ipv6Multicast",
+        f"{r'ipv4[-_ ]?labeled[-_ ]?Unicast$'}": "ipv4MplsLabels",
+        f"{r'ipv4[-_ ]?mpls[-_ ]?labels$'}": "ipv4MplsLabels",
+        f"{r'ipv6[-_ ]?labeled[-_ ]?Unicast$'}": "ipv6MplsLabels",
+        f"{r'ipv6[-_ ]?mpls[-_ ]?labels$'}": "ipv6MplsLabels",
+        f"{r'ipv4[-_ ]?sr[-_ ]?te$'}": "ipv4SrTe",  # codespell:ignore
+        f"{r'ipv6[-_ ]?sr[-_ ]?te$'}": "ipv6SrTe",  # codespell:ignore
+        f"{r'ipv4[-_ ]?mpls[-_ ]?vpn$'}": "ipv4MplsVpn",
+        f"{r'ipv6[-_ ]?mpls[-_ ]?vpn$'}": "ipv6MplsVpn",
+        f"{r'ipv4[-_ ]?Flow[-_ ]?spec$'}": "ipv4FlowSpec",
+        f"{r'ipv6[-_ ]?Flow[-_ ]?spec$'}": "ipv6FlowSpec",
+        f"{r'ipv4[-_ ]?Flow[-_ ]?spec[-_ ]?vpn$'}": "ipv4FlowSpecVpn",
+        f"{r'ipv6[-_ ]?Flow[-_ ]?spec[-_ ]?vpn$'}": "ipv6FlowSpecVpn",
+        f"{r'l2[-_ ]?vpn[-_ ]?vpls$'}": "l2VpnVpls",
+        f"{r'l2[-_ ]?vpn[-_ ]?evpn$'}": "l2VpnEvpn",
+        f"{r'link[-_ ]?state$'}": "linkState",
+        f"{r'rt[-_ ]?membership$'}": "rtMembership",
+        f"{r'ipv4[-_ ]?rt[-_ ]?membership$'}": "rtMembership",
+        f"{r'ipv4[-_ ]?mvpn$'}": "ipv4Mvpn",
     }
-
     for pattern, replacement in patterns.items():
-        match = re.search(pattern, value, re.IGNORECASE)
+        match = re.match(pattern, value, re.IGNORECASE)
         if match:
             return replacement
-
     return value
 
 
@@ -145,7 +166,31 @@ Safi = Literal["unicast", "multicast", "labeled-unicast", "sr-te"]
 EncryptionAlgorithm = Literal["RSA", "ECDSA"]
 RsaKeySize = Literal[2048, 3072, 4096]
 EcdsaKeySize = Literal[256, 384, 512]
-MultiProtocolCaps = Annotated[str, BeforeValidator(bgp_multiprotocol_capabilities_abbreviations)]
+MultiProtocolCaps = Annotated[
+    Literal[
+        "dps",
+        "ipv4Unicast",
+        "ipv6Unicast",
+        "ipv4Multicast",
+        "ipv6Multicast",
+        "ipv4MplsLabels",
+        "ipv6MplsLabels",
+        "ipv4SrTe",
+        "ipv6SrTe",
+        "ipv4MplsVpn",
+        "ipv6MplsVpn",
+        "ipv4FlowSpec",
+        "ipv6FlowSpec",
+        "ipv4FlowSpecVpn",
+        "ipv6FlowSpecVpn",
+        "l2VpnVpls",
+        "l2VpnEvpn",
+        "linkState",
+        "rtMembership",
+        "ipv4Mvpn",
+    ],
+    BeforeValidator(bgp_multiprotocol_capabilities_abbreviations),
+]
 BfdInterval = Annotated[int, Field(ge=50, le=60000)]
 BfdMultiplier = Annotated[int, Field(ge=3, le=50)]
 ErrDisableReasons = Literal[


Test patch:
diff --git a/anta/tests/routing/bgp.py b/anta/tests/routing/bgp.py
index bffeda7e..aeab1e47 100644
--- a/anta/tests/routing/bgp.py
+++ b/anta/tests/routing/bgp.py
@@ -550,7 +550,8 @@ class VerifyBGPPeerMPCaps(AntaTest):
                 vrf: default
                 strict: False
                 capabilities:
-                  - ipv4Unicast
+                  - ipv4 labeled-Unicast
+                  - ipv4MplsVpn
     ```
     """
 
diff --git a/anta/tests/routing/isis.py b/anta/tests/routing/isis.py
index 562ff6d6..3f1f862e 100644
--- a/anta/tests/routing/isis.py
+++ b/anta/tests/routing/isis.py
@@ -592,9 +592,6 @@ class VerifyISISSegmentRoutingTunnels(AntaTest):
         command_output = self.instance_commands[0].json_output
         self.result.is_success()
 
-        # initiate defaults
-        failure_message = []
-
         if len(command_output["entries"]) == 0:
             self.result.is_skipped("IS-IS-SR is not running on device.")
             return
@@ -602,129 +599,31 @@ class VerifyISISSegmentRoutingTunnels(AntaTest):
         for input_entry in self.inputs.entries:
             eos_entry = self._eos_entry_lookup(search_value=input_entry.endpoint, entries=command_output["entries"])
             if eos_entry is None:
-                failure_message.append(f"Tunnel to {input_entry} is not found.")
+                self.result.is_failure(f"Tunnel to {input_entry.endpoint!s} is not found.")
             elif input_entry.vias is not None:
-                failure_src = []
                 for via_input in input_entry.vias:
-                    if not self._check_tunnel_type(via_input, eos_entry):
-                        failure_src.append("incorrect tunnel type")
-                    if not self._check_tunnel_nexthop(via_input, eos_entry):
-                        failure_src.append("incorrect nexthop")
-                    if not self._check_tunnel_interface(via_input, eos_entry):
-                        failure_src.append("incorrect interface")
-                    if not self._check_tunnel_id(via_input, eos_entry):
-                        failure_src.append("incorrect tunnel ID")
-
-                if failure_src:
-                    failure_message.append(f"Tunnel to {input_entry.endpoint!s} is incorrect: {', '.join(failure_src)}")
-
-        if failure_message:
-            self.result.is_failure("\n".join(failure_message))
-
-    def _check_tunnel_type(self, via_input: VerifyISISSegmentRoutingTunnels.Input.Entry.Vias, eos_entry: dict[str, Any]) -> bool:
-        """Check if the tunnel type specified in `via_input` matches any of the tunnel types in `eos_entry`.
-
-        Parameters
-        ----------
-        via_input : VerifyISISSegmentRoutingTunnels.Input.Entry.Vias
-            The input tunnel type to check.
-        eos_entry : dict[str, Any]
-            The EOS entry containing the tunnel types.
-
-        Returns
-        -------
-        bool
-            True if the tunnel type matches any of the tunnel types in `eos_entry`, False otherwise.
-        """
-        if via_input.type is not None:
-            return any(
-                via_input.type
-                == get_value(
-                    dictionary=eos_via,
-                    key="type",
-                    default="undefined",
-                )
-                for eos_via in eos_entry["vias"]
-            )
-        return True
-
-    def _check_tunnel_nexthop(self, via_input: VerifyISISSegmentRoutingTunnels.Input.Entry.Vias, eos_entry: dict[str, Any]) -> bool:
-        """Check if the tunnel nexthop matches the given input.
-
-        Parameters
-        ----------
-        via_input : VerifyISISSegmentRoutingTunnels.Input.Entry.Vias
-            The input via object.
-        eos_entry : dict[str, Any]
-            The EOS entry dictionary.
-
-        Returns
-        -------
-        bool
-            True if the tunnel nexthop matches, False otherwise.
-        """
-        if via_input.nexthop is not None:
-            return any(
-                str(via_input.nexthop)
-                == get_value(
-                    dictionary=eos_via,
-                    key="nexthop",
-                    default="undefined",
-                )
-                for eos_via in eos_entry["vias"]
-            )
-        return True
-
-    def _check_tunnel_interface(self, via_input: VerifyISISSegmentRoutingTunnels.Input.Entry.Vias, eos_entry: dict[str, Any]) -> bool:
-        """Check if the tunnel interface exists in the given EOS entry.
-
-        Parameters
-        ----------
-        via_input : VerifyISISSegmentRoutingTunnels.Input.Entry.Vias
-            The input via object.
-        eos_entry : dict[str, Any]
-            The EOS entry dictionary.
+                    via_search_result = any(self._via_matches(via_input, eos_via) for eos_via in eos_entry["vias"])
+                    if not via_search_result:
+                        self.result.is_failure(f"Tunnel to {input_entry.endpoint!s} is incorrect.")
 
-        Returns
-        -------
-        bool
-            True if the tunnel interface exists, False otherwise.
-        """
-        if via_input.interface is not None:
-            return any(
-                via_input.interface
-                == get_value(
-                    dictionary=eos_via,
-                    key="interface",
-                    default="undefined",
-                )
-                for eos_via in eos_entry["vias"]
-            )
-        return True
-
-    def _check_tunnel_id(self, via_input: VerifyISISSegmentRoutingTunnels.Input.Entry.Vias, eos_entry: dict[str, Any]) -> bool:
-        """Check if the tunnel ID matches any of the tunnel IDs in the EOS entry's vias.
+    def _via_matches(self, via_input: VerifyISISSegmentRoutingTunnels.Input.Entry.Vias, eos_via: dict[str, Any]) -> bool:
+        """Check if the via input matches the eos via.
 
         Parameters
         ----------
         via_input : VerifyISISSegmentRoutingTunnels.Input.Entry.Vias
-            The input vias to check.
-        eos_entry : dict[str, Any])
-            The EOS entry to compare against.
+            The input via to check.
+        eos_via : dict[str, Any]
+            The EOS via to compare against.
 
         Returns
         -------
         bool
-            True if the tunnel ID matches any of the tunnel IDs in the EOS entry's vias, False otherwise.
+            True if the via input matches the eos via, False otherwise.
         """
-        if via_input.tunnel_id is not None:
-            return any(
-                via_input.tunnel_id.upper()
-                == get_value(
-                    dictionary=eos_via,
-                    key="tunnelId.type",
-                    default="undefined",
-                ).upper()
-                for eos_via in eos_entry["vias"]
-            )
-        return True
+        return (
+            (via_input.type is None or via_input.type == eos_via.get("type"))
+            and (via_input.nexthop is None or str(via_input.nexthop) == eos_via.get("nexthop"))
+            and (via_input.interface is None or via_input.interface == eos_via.get("interface"))
+            and (via_input.tunnel_id is None or via_input.tunnel_id.upper() == get_value(eos_via, "tunnelId.type", default="").upper())
+        )
diff --git a/examples/tests.yaml b/examples/tests.yaml
index b190ec3c..61b13870 100644
--- a/examples/tests.yaml
+++ b/examples/tests.yaml
@@ -456,7 +456,8 @@ anta.tests.routing.bgp:
           vrf: default
           strict: False
           capabilities:
-            - ipv4Unicast
+            - ipv4 labeled-Unicast
+            - ipv4MplsVpn
   - VerifyBGPPeerRouteLimit:
       # Verifies maximum routes and warning limit for BGP IPv4 peer(s).
       bgp_peers:
diff --git a/tests/units/anta_tests/routing/test_bgp.py b/tests/units/anta_tests/routing/test_bgp.py
index 21758ea7..f7549923 100644
--- a/tests/units/anta_tests/routing/test_bgp.py
+++ b/tests/units/anta_tests/routing/test_bgp.py
@@ -1384,12 +1384,12 @@ DATA: list[dict[str, Any]] = [
                 {
                     "peer_address": "172.30.11.1",
                     "vrf": "default",
-                    "capabilities": ["Ipv4 Unicast", "ipv4 Mpls labels"],
+                    "capabilities": ["Ipv4Unicast", "ipv4 Mpls labels"],
                 },
                 {
                     "peer_address": "172.30.11.10",
                     "vrf": "MGMT",
-                    "capabilities": ["ipv4 Unicast", "ipv4 MplsVpn"],
+                    "capabilities": ["ipv4_Unicast", "ipv4 MplsVpn"],
                 },
             ]
         },
@@ -1441,12 +1441,12 @@ DATA: list[dict[str, Any]] = [
                 {
                     "peer_address": "172.30.11.10",
                     "vrf": "default",
-                    "capabilities": ["ipv4Unicast", "L2 Vpn EVPN"],
+                    "capabilities": ["ipv4Unicast", "l2-vpn-EVPN"],
                 },
                 {
                     "peer_address": "172.30.11.1",
                     "vrf": "MGMT",
-                    "capabilities": ["ipv4Unicast", "L2 Vpn EVPN"],
+                    "capabilities": ["ipv4Unicast", "l2vpnevpn"],
                 },
             ]
         },
@@ -1575,7 +1575,7 @@ DATA: list[dict[str, Any]] = [
                 {
                     "peer_address": "172.30.11.10",
                     "vrf": "MGMT",
-                    "capabilities": ["ipv4unicast", "ipv4 mplsvpn", "L2vpnEVPN"],
+                    "capabilities": ["ipv4_unicast", "ipv4 mplsvpn", "L2vpnEVPN"],
                 },
                 {
                     "peer_address": "172.30.11.11",
@@ -1656,13 +1656,13 @@ DATA: list[dict[str, Any]] = [
                     "peer_address": "172.30.11.1",
                     "vrf": "default",
                     "strict": True,
-                    "capabilities": ["Ipv4 Unicast", "ipv4 Mpls labels"],
+                    "capabilities": ["Ipv4 Unicast", "ipv4MplsLabels"],
                 },
                 {
                     "peer_address": "172.30.11.10",
                     "vrf": "MGMT",
                     "strict": True,
-                    "capabilities": ["ipv4 Unicast", "ipv4 MplsVpn"],
+                    "capabilities": ["ipv4-Unicast", "ipv4MplsVpn"],
                 },
             ]
         },
diff --git a/tests/units/anta_tests/routing/test_isis.py b/tests/units/anta_tests/routing/test_isis.py
index 9c379eae..a885d065 100644
--- a/tests/units/anta_tests/routing/test_isis.py
+++ b/tests/units/anta_tests/routing/test_isis.py
@@ -1405,7 +1405,7 @@ DATA: list[dict[str, Any]] = [
         },
         "expected": {
             "result": "failure",
-            "messages": ["Tunnel to endpoint=IPv4Network('1.0.0.122/32') vias=None is not found."],
+            "messages": ["Tunnel to 1.0.0.122/32 is not found."],
         },
     },
     {
@@ -1486,7 +1486,7 @@ DATA: list[dict[str, Any]] = [
         },
         "expected": {
             "result": "failure",
-            "messages": ["Tunnel to 1.0.0.13/32 is incorrect: incorrect tunnel type"],
+            "messages": ["Tunnel to 1.0.0.13/32 is incorrect."],
         },
     },
     {
@@ -1574,7 +1574,7 @@ DATA: list[dict[str, Any]] = [
         },
         "expected": {
             "result": "failure",
-            "messages": ["Tunnel to 1.0.0.122/32 is incorrect: incorrect nexthop"],
+            "messages": ["Tunnel to 1.0.0.122/32 is incorrect."],
         },
     },
     {
@@ -1662,7 +1662,7 @@ DATA: list[dict[str, Any]] = [
         },
         "expected": {
             "result": "failure",
-            "messages": ["Tunnel to 1.0.0.122/32 is incorrect: incorrect interface"],
+            "messages": ["Tunnel to 1.0.0.122/32 is incorrect."],
         },
     },
     {
@@ -1750,7 +1750,7 @@ DATA: list[dict[str, Any]] = [
         },
         "expected": {
             "result": "failure",
-            "messages": ["Tunnel to 1.0.0.122/32 is incorrect: incorrect nexthop"],
+            "messages": ["Tunnel to 1.0.0.122/32 is incorrect."],
         },
     },
     {
@@ -1837,7 +1837,28 @@ DATA: list[dict[str, Any]] = [
         },
         "expected": {
             "result": "failure",
-            "messages": ["Tunnel to 1.0.0.111/32 is incorrect: incorrect tunnel ID"],
+            "messages": ["Tunnel to 1.0.0.111/32 is incorrect."],
+        },
+    },
+    {
+        "test": VerifyISISSegmentRoutingTunnels,
+        "name": "skipped with ISIS-SR not running",
+        "eos_data": [{"entries": {}}],
+        "inputs": {
+            "entries": [
+                {"endpoint": "1.0.0.122/32"},
+                {"endpoint": "1.0.0.13/32", "vias": [{"type": "ip"}]},
+                {
+                    "endpoint": "1.0.0.111/32",
+                    "vias": [
+                        {"type": "tunnel", "tunnel_id": "unset"},
+                    ],
+                },
+            ]
+        },
+        "expected": {
+            "result": "skipped",
+            "messages": ["IS-IS-SR is not running on device."],
         },
     },
 ]
diff --git a/tests/units/test_custom_types.py b/tests/units/test_custom_types.py
index 5a92092c..71f13e08 100644
--- a/tests/units/test_custom_types.py
+++ b/tests/units/test_custom_types.py
@@ -15,11 +15,7 @@ import re
 import pytest
 
 from anta.custom_types import (
-    REGEX_BGP_IPV4_MPLS_VPN,
-    REGEX_BGP_IPV4_UNICAST,
     REGEX_TYPE_PORTCHANNEL,
-    REGEXP_BGP_IPV4_MPLS_LABELS,
-    REGEXP_BGP_L2VPN_AFI,
     REGEXP_INTERFACE_ID,
     REGEXP_PATH_MARKERS,
     REGEXP_TYPE_EOS_INTERFACE,
@@ -50,40 +46,6 @@ def test_regexp_path_markers() -> 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}")
@@ -209,13 +171,29 @@ def test_interface_autocomplete_failure() -> None:
     ("str_input", "expected_output"),
     [
         pytest.param("L2VPNEVPN", "l2VpnEvpn", id="l2VpnEvpn"),
-        pytest.param("ipv4-mplsLabels", "ipv4MplsLabels", id="ipv4MplsLabels"),
+        pytest.param("IPv4 Labeled Unicast", "ipv4MplsLabels", id="ipv4MplsLabels"),
         pytest.param("ipv4-mpls-vpn", "ipv4MplsVpn", id="ipv4MplsVpn"),
-        pytest.param("ipv4-unicast", "ipv4Unicast", id="ipv4Unicast"),
-        pytest.param("BLAH", "BLAH", id="unmatched"),
+        pytest.param("ipv4_unicast", "ipv4Unicast", id="ipv4Unicast"),
+        pytest.param("ipv4 Mvpn", "ipv4Mvpn", id="ipv4Mvpn"),
+        pytest.param("ipv4_Flow-Spec Vpn", "ipv4FlowSpecVpn", id="ipv4FlowSpecVpn"),
+        pytest.param("Dynamic-Path-Selection", "dps", id="dps"),
+        pytest.param("ipv6unicast", "ipv6Unicast", id="ipv6Unicast"),
+        pytest.param("IPv4-Multicast", "ipv4Multicast", id="ipv4Multicast"),
+        pytest.param("IPv6_multicast", "ipv6Multicast", id="ipv6Multicast"),
+        pytest.param("ipv6_Mpls-Labels", "ipv6MplsLabels", id="ipv6MplsLabels"),
+        pytest.param("IPv4_SR_TE", "ipv4SrTe", id="ipv4SrTe"),
+        pytest.param("iPv6-sR-tE", "ipv6SrTe", id="ipv6SrTe"),
+        pytest.param("ipv6_mpls-vpn", "ipv6MplsVpn", id="ipv6MplsVpn"),
+        pytest.param("IPv4 Flow-spec", "ipv4FlowSpec", id="ipv4FlowSpec"),
+        pytest.param("IPv6Flow_spec", "ipv6FlowSpec", id="ipv6FlowSpec"),
+        pytest.param("ipv6 Flow-Spec Vpn", "ipv6FlowSpecVpn", id="ipv6FlowSpecVpn"),
+        pytest.param("L2VPN VPLS", "l2VpnVpls", id="l2VpnVpls"),
+        pytest.param("link-state", "linkState", id="linkState"),
+        pytest.param("RT_Membership", "rtMembership", id="rtMembership"),
+        pytest.param("ipv4-RT_Membership", "rtMembership", id="rtMembership"),
     ],
 )
-def test_bgp_multiprotocol_capabilities_abbreviationsh(str_input: str, expected_output: str) -> None:
+def test_bgp_multiprotocol_capabilities_abbreviations(str_input: str, expected_output: str) -> None:
     """Test bgp_multiprotocol_capabilities_abbreviations."""
     assert bgp_multiprotocol_capabilities_abbreviations(str_input) == expected_output
 
@@ -257,11 +235,7 @@ def test_interface_case_sensitivity_uppercase() -> None:
 @pytest.mark.parametrize(
     "str_input",
     [
-        REGEX_BGP_IPV4_MPLS_VPN,
-        REGEX_BGP_IPV4_UNICAST,
         REGEX_TYPE_PORTCHANNEL,
-        REGEXP_BGP_IPV4_MPLS_LABELS,
-        REGEXP_BGP_L2VPN_AFI,
         REGEXP_INTERFACE_ID,
         REGEXP_PATH_MARKERS,
         REGEXP_TYPE_EOS_INTERFACE,