This repository has been archived on 2025-03-20. You can view files and clone it, but cannot push or open issues or pull requests.
sonic-buildimage/src/sonic-dhcp-utilities/tests/test_utils.py
Yaqiang Zhu b2ca36aa1c
[smart_switch][dhcp_server] Add smart_switch support in dhcpservd (#17576)
* [smart_switch][dhcp_server] Add related checker for smart_switch in dhcp_db_monitor
* [smart_switch][dhcp_server] Add smart_switch support in dhcpservd
2024-01-09 15:40:11 -08:00

161 lines
6.1 KiB
Python

import dhcp_utilities.common.utils as utils
import ipaddress
import psutil
import pytest
from swsscommon import swsscommon
from common_utils import MockProc
from unittest.mock import patch, call, PropertyMock
interval_test_data = {
"ordered_with_overlap": {
"intervals": [["192.168.0.2", "192.168.0.5"], ["192.168.0.3", "192.168.0.6"], ["192.168.0.10", "192.168.0.10"]],
"expected_res": [["192.168.0.2", "192.168.0.6"], ["192.168.0.10", "192.168.0.10"]]
},
"not_order_with_overlap": {
"intervals": [["192.168.0.3", "192.168.0.6"], ["192.168.0.2", "192.168.0.5"], ["192.168.0.10", "192.168.0.10"]],
"expected_res": [["192.168.0.2", "192.168.0.6"], ["192.168.0.10", "192.168.0.10"]]
},
"ordered_without_overlap": {
"intervals": [["192.168.0.2", "192.168.0.5"], ["192.168.0.10", "192.168.0.10"]],
"expected_res": [["192.168.0.2", "192.168.0.5"], ["192.168.0.10", "192.168.0.10"]]
},
"not_ordered_without_overlap": {
"intervals": [["192.168.0.10", "192.168.0.10"], ["192.168.0.2", "192.168.0.5"]],
"expected_res": [["192.168.0.2", "192.168.0.5"], ["192.168.0.10", "192.168.0.10"]]
},
"single_interval": {
"intervals": [["192.168.0.10", "192.168.0.10"]],
"expected_res": [["192.168.0.10", "192.168.0.10"]]
}
}
validate_str_type_data = [
# type, value, expected_res
["string", 123, False],
["string", "123", True],
["binary", "01020304ef", True],
# False because we only support octet-based binary
["binary", "01020304e", False],
["binary", "0102ab0304ef", True],
["binary", "we", False],
["boolean", "true", True],
["boolean", "false", True],
["boolean", "0", False],
["boolean", "1", False],
["boolean", True, False],
["boolean", "213", False],
["ipv4-address", "192.168.0.1", True],
["ipv4-address", "300.168.0.1", False],
["ipv4-address", 123, False],
["ipv4-address", "123", False],
["ipv4-address", "192.168.0.1/24", False],
["uint8", "e123", False],
["uint8", 123, False],
["uint8", "300", False],
["uint8", "128", True],
["uint16", "1000", True],
["uint16", "65536", False],
["uint32", "4294967296", False],
["uint32", "65536", True],
# False because we don't support uint64
["uint64", "65536", False]
]
def test_construct_without_sock(mock_swsscommon_dbconnector_init):
utils.DhcpDbConnector()
mock_swsscommon_dbconnector_init.assert_has_calls([
call(swsscommon.CONFIG_DB, "127.0.0.1", 6379, 0),
call(swsscommon.STATE_DB, "127.0.0.1", 6379, 0)
])
def test_construct_sock(mock_swsscommon_dbconnector_init):
redis_sock = "/var/run/redis/redis.sock"
dhcp_db_connector = utils.DhcpDbConnector(redis_sock=redis_sock)
assert dhcp_db_connector.redis_sock == redis_sock
mock_swsscommon_dbconnector_init.assert_has_calls([
call(swsscommon.CONFIG_DB, redis_sock, 0),
call(swsscommon.STATE_DB, redis_sock, 0)
])
def test_get_db_table(mock_swsscommon_dbconnector_init, mock_swsscommon_table_init):
dhcp_db_connector = utils.DhcpDbConnector()
with patch.object(swsscommon.Table, "getKeys", return_value=["key1", "key2"]) as mock_get_keys, \
patch.object(utils, "get_entry", return_value={"list": "1,2", "value": "3,4"}), \
patch.object(swsscommon.Table, "hget", side_effect=mock_hget):
ret = dhcp_db_connector.get_config_db_table("VLAN")
assert ret == {
"key1": {"list": ["1", "2"], "value": "3,4"},
"key2": {"list": ["1", "2"], "value": "3,4"}
}
ret = dhcp_db_connector.get_state_db_table("VLAN")
mock_swsscommon_table_init.assert_has_calls([
call(dhcp_db_connector.config_db, "VLAN"),
call(dhcp_db_connector.state_db, "VLAN")
])
mock_get_keys.assert_has_calls([
call(),
call()
])
assert ret == {
"key1": {"list": ["1", "2"], "value": "3,4"},
"key2": {"list": ["1", "2"], "value": "3,4"}
}
def test_get_entry(mock_swsscommon_dbconnector_init, mock_swsscommon_table_init):
tested_entry = {"key": "value"}
dhcp_db_connector = utils.DhcpDbConnector()
with patch.object(swsscommon.Table, "get", return_value=(None, tested_entry)) as mock_get:
res = utils.get_entry(swsscommon.Table(dhcp_db_connector.config_db, "VLAN"), "dummy_entry")
assert res == tested_entry
mock_get.assert_called_once_with("dummy_entry")
@pytest.mark.parametrize("test_type", interval_test_data.keys())
def test_merge_intervals(test_type):
intervals = convert_ip_address_intervals(interval_test_data[test_type]["intervals"])
expected_res = convert_ip_address_intervals(interval_test_data[test_type]["expected_res"])
assert utils.merge_intervals(intervals) == expected_res
def mock_hget(_, field):
if field == "list":
return False, ""
else:
return True, ""
def convert_ip_address_intervals(intervals):
ret = []
for interval in intervals:
ret.append([ipaddress.ip_address(interval[0]), ipaddress.ip_address(interval[1])])
return ret
@pytest.mark.parametrize("test_data", validate_str_type_data)
def test_validate_ttr_type(test_data):
res = utils.validate_str_type(test_data[0], test_data[1])
assert res == test_data[2]
def test_get_target_process_cmds():
with patch.object(psutil, "process_iter", return_value=[MockProc("dhcrelay", 1), MockProc("dhcpmon", 2)],
new_callable=PropertyMock):
res = utils.get_target_process_cmds("dhcrelay")
expected_res = [
[
"/usr/sbin/dhcrelay", "-d", "-m", "discard", "-a", "%h:%p", "%P", "--name-alias-map-file",
"/tmp/port-name-alias-map.txt", "-id", "Vlan1000", "-iu", "docker0", "240.127.1.2"
]
]
assert res == expected_res
@pytest.mark.parametrize("is_smart_switch", [True, False])
def test_is_smart_switch(is_smart_switch):
device_metadata = {"localhost": {"subtype": "SmartSwitch"}} if is_smart_switch else {"localhost": {}}
assert utils.is_smart_switch(device_metadata) == is_smart_switch