initial commit
This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
"""Unit tests for napalm_proxmox.utils."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
from napalm_proxmox import utils
|
||||
|
||||
|
||||
class TestNormalizeMAC:
|
||||
def test_colon_upper(self):
|
||||
assert utils.normalize_mac("AA:BB:CC:DD:EE:FF") == "aa:bb:cc:dd:ee:ff"
|
||||
|
||||
def test_dash_separated(self):
|
||||
assert utils.normalize_mac("AA-BB-CC-DD-EE-FF") == "aa:bb:cc:dd:ee:ff"
|
||||
|
||||
def test_lowercase_passthrough(self):
|
||||
assert utils.normalize_mac("aa:bb:cc:dd:ee:ff") == "aa:bb:cc:dd:ee:ff"
|
||||
|
||||
def test_empty(self):
|
||||
assert utils.normalize_mac("") == ""
|
||||
|
||||
|
||||
class TestParseCIDR:
|
||||
def test_ipv4(self):
|
||||
ip, plen = utils.parse_cidr("192.168.1.1/24")
|
||||
assert ip == "192.168.1.1"
|
||||
assert plen == 24
|
||||
|
||||
def test_ipv6(self):
|
||||
ip, plen = utils.parse_cidr("2001:db8::1/64")
|
||||
assert ip == "2001:db8::1"
|
||||
assert plen == 64
|
||||
|
||||
def test_no_prefix(self):
|
||||
ip, plen = utils.parse_cidr("10.0.0.1")
|
||||
assert ip == "10.0.0.1"
|
||||
assert plen == 32
|
||||
|
||||
def test_host_route(self):
|
||||
ip, plen = utils.parse_cidr("10.0.0.1/32")
|
||||
assert plen == 32
|
||||
|
||||
|
||||
class TestPrefixLength:
|
||||
def test_slash24(self):
|
||||
assert utils.prefix_length("10.0.0.0/24") == 24
|
||||
|
||||
def test_slash_16(self):
|
||||
assert utils.prefix_length("192.168.0.0/16") == 16
|
||||
|
||||
def test_no_slash(self):
|
||||
assert utils.prefix_length("10.0.0.1") == 32
|
||||
|
||||
|
||||
class TestAddressesFromNodeNetwork:
|
||||
def test_address_and_netmask(self):
|
||||
data = {"address": "10.0.0.1", "netmask": "255.255.255.0"}
|
||||
result = utils.addresses_from_node_network(data)
|
||||
assert "ipv4" in result
|
||||
assert "10.0.0.1" in result["ipv4"]
|
||||
assert result["ipv4"]["10.0.0.1"]["prefix_length"] == 24
|
||||
|
||||
def test_cidr_ipv4(self):
|
||||
data = {"cidr": "10.0.0.1/24"}
|
||||
result = utils.addresses_from_node_network(data)
|
||||
assert "ipv4" in result
|
||||
assert "10.0.0.1" in result["ipv4"]
|
||||
|
||||
def test_cidr_ipv6(self):
|
||||
data = {"cidr6": "2001:db8::1/64"}
|
||||
result = utils.addresses_from_node_network(data)
|
||||
assert "ipv6" in result
|
||||
assert "2001:db8::1" in result["ipv6"]
|
||||
assert result["ipv6"]["2001:db8::1"]["prefix_length"] == 64
|
||||
|
||||
def test_both_ipv4_and_ipv6(self):
|
||||
data = {"cidr": "10.0.0.1/24", "cidr6": "2001:db8::1/64"}
|
||||
result = utils.addresses_from_node_network(data)
|
||||
assert "ipv4" in result
|
||||
assert "ipv6" in result
|
||||
|
||||
def test_empty_input(self):
|
||||
result = utils.addresses_from_node_network({})
|
||||
assert result == {}
|
||||
|
||||
|
||||
class TestIsOVSInterface:
|
||||
def test_ovs_bridge(self):
|
||||
assert utils.is_ovs_interface({"type": "OVSBridge"}) is True
|
||||
|
||||
def test_ovs_bond(self):
|
||||
assert utils.is_ovs_interface({"type": "OVSBond"}) is True
|
||||
|
||||
def test_ovs_int_port(self):
|
||||
assert utils.is_ovs_interface({"type": "OVSIntPort"}) is True
|
||||
|
||||
def test_linux_bridge(self):
|
||||
assert utils.is_ovs_interface({"type": "bridge"}) is False
|
||||
|
||||
def test_eth(self):
|
||||
assert utils.is_ovs_interface({"type": "eth"}) is False
|
||||
|
||||
def test_no_type_key(self):
|
||||
assert utils.is_ovs_interface({}) is False
|
||||
|
||||
|
||||
class TestIsSDNVNet:
|
||||
def test_vnet_pattern(self):
|
||||
assert utils.is_sdn_vnet("vnet0") is True
|
||||
assert utils.is_sdn_vnet("vnet99") is True
|
||||
|
||||
def test_non_vnet(self):
|
||||
assert utils.is_sdn_vnet("eth0") is False
|
||||
assert utils.is_sdn_vnet("vmbr0") is False
|
||||
|
||||
def test_vnet_with_suffix(self):
|
||||
assert utils.is_sdn_vnet("vnet0sub") is False
|
||||
|
||||
|
||||
class TestSpeedMbps:
|
||||
def test_speed_present(self):
|
||||
assert utils.speed_mbps({"speed": "1000"}) == 1000.0
|
||||
|
||||
def test_speed_mbit_suffix(self):
|
||||
# Some entries may have "Mbit" unit in the string — handled by parsing
|
||||
assert utils.speed_mbps({"speed": "10000"}) == 10000.0
|
||||
|
||||
def test_no_speed(self):
|
||||
assert utils.speed_mbps({}) == -1.0
|
||||
|
||||
def test_speed_non_numeric(self):
|
||||
assert utils.speed_mbps({"speed": "unknown"}) == -1.0
|
||||
|
||||
|
||||
class TestSDNZoneToNetworkInstance:
|
||||
def test_vlan_zone(self):
|
||||
zone = {"zone": "z1", "type": "vlan", "mtu": 1500}
|
||||
result = utils.sdn_zone_to_network_instance(zone)
|
||||
assert result["type"] == "L2VPN"
|
||||
assert result["name"] == "z1"
|
||||
|
||||
def test_evpn_zone(self):
|
||||
zone = {"zone": "z2", "type": "evpn", "peers": "10.0.0.1", "rt": 10001}
|
||||
result = utils.sdn_zone_to_network_instance(zone)
|
||||
assert result["type"] == "L3VRF"
|
||||
|
||||
def test_vxlan_zone(self):
|
||||
zone = {"zone": "z3", "type": "vxlan", "mtu": 9000}
|
||||
result = utils.sdn_zone_to_network_instance(zone)
|
||||
assert result["type"] == "L2VPN"
|
||||
|
||||
def test_simple_zone(self):
|
||||
zone = {"zone": "z4", "type": "simple"}
|
||||
result = utils.sdn_zone_to_network_instance(zone)
|
||||
assert result["type"] == "L3VRF"
|
||||
|
||||
def test_unknown_zone_type(self):
|
||||
zone = {"zone": "z5", "type": "qinq"}
|
||||
result = utils.sdn_zone_to_network_instance(zone)
|
||||
assert result["type"] == "L2VPN"
|
||||
|
||||
def test_result_has_interfaces(self):
|
||||
zone = {"zone": "z1", "type": "vlan"}
|
||||
result = utils.sdn_zone_to_network_instance(zone)
|
||||
assert "interfaces" in result
|
||||
|
||||
|
||||
class TestParseARPOutput:
|
||||
ARP_N = (
|
||||
"Address HWtype HWaddress Flags Iface\n"
|
||||
"10.0.0.254 ether aa:bb:cc:dd:ee:ff C eth0\n"
|
||||
"10.0.0.10 ether 11:22:33:44:55:66 C vmbr0\n"
|
||||
"? (10.0.0.20) at <incomplete> on eth0\n"
|
||||
)
|
||||
|
||||
def test_parses_two_entries(self):
|
||||
result = utils.parse_arp_output(self.ARP_N)
|
||||
assert len(result) == 2
|
||||
|
||||
def test_entry_fields(self):
|
||||
result = utils.parse_arp_output(self.ARP_N)
|
||||
assert result[0]["ip"] == "10.0.0.254"
|
||||
assert result[0]["mac"] == "aa:bb:cc:dd:ee:ff"
|
||||
assert result[0]["interface"] == "eth0"
|
||||
|
||||
def test_skips_incomplete(self):
|
||||
result = utils.parse_arp_output(self.ARP_N)
|
||||
ips = {e["ip"] for e in result}
|
||||
assert "10.0.0.20" not in ips
|
||||
|
||||
def test_empty_input(self):
|
||||
result = utils.parse_arp_output("")
|
||||
assert result == []
|
||||
|
||||
|
||||
class TestParseOVSVsctlShow:
|
||||
RAW = (
|
||||
" Bridge vmbr1\n"
|
||||
" Port eth1\n"
|
||||
" Port vnet0\n"
|
||||
" Port vmbr1\n"
|
||||
" Bridge vmbr2\n"
|
||||
" Port eth2\n"
|
||||
" Port vmbr2\n"
|
||||
)
|
||||
|
||||
def test_finds_both_bridges(self):
|
||||
result = utils.parse_ovs_vsctl_show(self.RAW)
|
||||
assert "vmbr1" in result
|
||||
assert "vmbr2" in result
|
||||
|
||||
def test_ports_exclude_self(self):
|
||||
result = utils.parse_ovs_vsctl_show(self.RAW)
|
||||
assert "vmbr1" not in result["vmbr1"]["ports"]
|
||||
assert "vmbr2" not in result["vmbr2"]["ports"]
|
||||
|
||||
def test_ports_included(self):
|
||||
result = utils.parse_ovs_vsctl_show(self.RAW)
|
||||
assert "eth1" in result["vmbr1"]["ports"]
|
||||
assert "eth2" in result["vmbr2"]["ports"]
|
||||
|
||||
def test_empty_input(self):
|
||||
result = utils.parse_ovs_vsctl_show("")
|
||||
assert result == {}
|
||||
Reference in New Issue
Block a user