From ce95f26a404367edc15f94b51a10fae69b7f9d6f Mon Sep 17 00:00:00 2001 From: trzhang-msft Date: Wed, 15 Sep 2021 12:14:44 -0700 Subject: [PATCH] caclmgrd: add test code to check dhcp acl update (#8509) - add test code to check dhcp acl update - port #8359 (caclmgrd: add test code to check dhcp acl update) to 202012 branch --- src/sonic-host-services/pytest.ini | 2 +- src/sonic-host-services/setup.py | 1 + .../tests/caclmgrd/__init__.py | 0 .../tests/caclmgrd/caclmgrd_dhcp_test.py | 54 ++++++ .../tests/caclmgrd/test_dhcp_vectors.py | 163 ++++++++++++++++++ .../{hostcfgd => common}/mock_configdb.py | 2 +- .../tests/hostcfgd/hostcfgd_test.py | 2 +- 7 files changed, 221 insertions(+), 3 deletions(-) create mode 100644 src/sonic-host-services/tests/caclmgrd/__init__.py create mode 100644 src/sonic-host-services/tests/caclmgrd/caclmgrd_dhcp_test.py create mode 100644 src/sonic-host-services/tests/caclmgrd/test_dhcp_vectors.py rename src/sonic-host-services/tests/{hostcfgd => common}/mock_configdb.py (96%) diff --git a/src/sonic-host-services/pytest.ini b/src/sonic-host-services/pytest.ini index 5a1e1dc943..781d242a3a 100644 --- a/src/sonic-host-services/pytest.ini +++ b/src/sonic-host-services/pytest.ini @@ -1,2 +1,2 @@ [pytest] -addopts = --cov=scripts --cov-report html --cov-report term --cov-report xml --ignore=tests/hostcfgd/test_vectors.py +addopts = --cov=scripts --cov-report html --cov-report term --cov-report xml --ignore=tests/hostcfgd/test_vectors.py --ignore=tests/caclmgrd/test_dhcp_vectors.py diff --git a/src/sonic-host-services/setup.py b/src/sonic-host-services/setup.py index 98f5394997..6d3add214f 100644 --- a/src/sonic-host-services/setup.py +++ b/src/sonic-host-services/setup.py @@ -28,6 +28,7 @@ setup( tests_require = [ 'parameterized', 'pytest', + 'pyfakefs', 'sonic-py-common' ], classifiers = [ diff --git a/src/sonic-host-services/tests/caclmgrd/__init__.py b/src/sonic-host-services/tests/caclmgrd/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/sonic-host-services/tests/caclmgrd/caclmgrd_dhcp_test.py b/src/sonic-host-services/tests/caclmgrd/caclmgrd_dhcp_test.py new file mode 100644 index 0000000000..4624f11bb9 --- /dev/null +++ b/src/sonic-host-services/tests/caclmgrd/caclmgrd_dhcp_test.py @@ -0,0 +1,54 @@ +import os +import sys + +from swsscommon import swsscommon +from parameterized import parameterized +from sonic_py_common.general import load_module_from_source +from unittest import TestCase, mock +from pyfakefs.fake_filesystem_unittest import patchfs + +from .test_dhcp_vectors import CACLMGRD_DHCP_TEST_VECTOR +from tests.common.mock_configdb import MockConfigDb + + +DBCONFIG_PATH = '/var/run/redis/sonic-db/database_config.json' + + +swsscommon.ConfigDBConnector = MockConfigDb +test_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +modules_path = os.path.dirname(test_path) +scripts_path = os.path.join(modules_path, "scripts") +sys.path.insert(0, modules_path) +caclmgrd_path = os.path.join(scripts_path, 'caclmgrd') +caclmgrd = load_module_from_source('caclmgrd', caclmgrd_path) + + +class TestCaclmgrdDhcp(TestCase): + """ + Test caclmgrd dhcp + """ + @parameterized.expand(CACLMGRD_DHCP_TEST_VECTOR) + @patchfs + def test_caclmgrd_dhcp(self, test_name, test_data, fs): + if not os.path.exists(DBCONFIG_PATH): + fs.create_file(DBCONFIG_PATH) # fake database_config.json + + MockConfigDb.set_config_db(test_data["config_db"]) + + with mock.patch("caclmgrd.subprocess") as mocked_subprocess: + popen_mock = mock.Mock() + popen_attrs = test_data["popen_attributes"] + popen_mock.configure_mock(**popen_attrs) + mocked_subprocess.Popen.return_value = popen_mock + + call_mock = mock.Mock() + call_rc = test_data["call_rc"] + mocked_subprocess.call.return_value = call_rc + + caclmgrd_daemon = caclmgrd.ControlPlaneAclManager("caclmgrd") + mux_update = test_data["mux_update"] + + for key,data in mux_update: + caclmgrd_daemon.update_dhcp_acl(key, '', data) + + mocked_subprocess.call.assert_has_calls(test_data["expected_subprocess_calls"], any_order=False) diff --git a/src/sonic-host-services/tests/caclmgrd/test_dhcp_vectors.py b/src/sonic-host-services/tests/caclmgrd/test_dhcp_vectors.py new file mode 100644 index 0000000000..6a58f76125 --- /dev/null +++ b/src/sonic-host-services/tests/caclmgrd/test_dhcp_vectors.py @@ -0,0 +1,163 @@ +from unittest.mock import call + +""" + caclmgrd dhcp test vector +""" +CACLMGRD_DHCP_TEST_VECTOR = [ + [ + "Active_Present", + { + "config_db": { + "DEVICE_METADATA": { + "localhost": { + "subtype": "DualToR", + "type": "ToRRouter", + } + }, + }, + "mux_update": [ + ("Ethernet4", {"state": "active"}), + ("Ethernet8", {"state": "active"}), + ], + "expected_subprocess_calls": [ + call("iptables --check DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --delete DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --check DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), + call("iptables --delete DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), + ], + "popen_attributes": { + 'communicate.return_value': ('output', 'error'), + }, + "call_rc": 0, + }, + ], + [ + "Active_Absent", + { + "config_db": { + "DEVICE_METADATA": { + "localhost": { + "subtype": "DualToR", + "type": "ToRRouter", + } + }, + }, + "mux_update": [ + ("Ethernet4", {"state": "active"}), + ("Ethernet8", {"state": "active"}), + ], + "expected_subprocess_calls": [ + call("iptables --check DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --check DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), + ], + "popen_attributes": { + 'communicate.return_value': ('output', 'error'), + }, + "call_rc": 1, + }, + ], + [ + "Standby_Present", + { + "config_db": { + "DEVICE_METADATA": { + "localhost": { + "subtype": "DualToR", + "type": "ToRRouter", + } + }, + }, + "mux_update": [ + ("Ethernet4", {"state": "standby"}), + ("Ethernet8", {"state": "standby"}), + ], + "expected_subprocess_calls": [ + call("iptables --check DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --check DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), + ], + "popen_attributes": { + 'communicate.return_value': ('output', 'error'), + }, + "call_rc": 0, + }, + ], + [ + "Standby_Absent", + { + "config_db": { + "DEVICE_METADATA": { + "localhost": { + "subtype": "DualToR", + "type": "ToRRouter", + } + }, + }, + "mux_update": [ + ("Ethernet4", {"state": "standby"}), + ("Ethernet8", {"state": "standby"}), + ], + "expected_subprocess_calls": [ + call("iptables --check DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --insert DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --check DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), + call("iptables --insert DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), + ], + "popen_attributes": { + 'communicate.return_value': ('output', 'error'), + }, + "call_rc": 1, + }, + ], + [ + "Unknown_Present", + { + "config_db": { + "DEVICE_METADATA": { + "localhost": { + "subtype": "DualToR", + "type": "ToRRouter", + } + }, + }, + "mux_update": [ + ("Ethernet4", {"state": "unknown"}), + ("Ethernet8", {"state": "unknown"}), + ], + "expected_subprocess_calls": [ + call("iptables --check DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --delete DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --check DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), + call("iptables --delete DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), + ], + "popen_attributes": { + 'communicate.return_value': ('output', 'error'), + }, + "call_rc": 0, + }, + ], + [ + "Uknown_Absent", + { + "config_db": { + "DEVICE_METADATA": { + "localhost": { + "subtype": "DualToR", + "type": "ToRRouter", + } + }, + }, + "mux_update": [ + ("Ethernet4", {"state": "unknown"}), + ("Ethernet8", {"state": "unknown"}), + ], + "expected_subprocess_calls": [ + call("iptables --check DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --check DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), + ], + "popen_attributes": { + 'communicate.return_value': ('output', 'error'), + }, + "call_rc": 1, + }, + ], +] diff --git a/src/sonic-host-services/tests/hostcfgd/mock_configdb.py b/src/sonic-host-services/tests/common/mock_configdb.py similarity index 96% rename from src/sonic-host-services/tests/hostcfgd/mock_configdb.py rename to src/sonic-host-services/tests/common/mock_configdb.py index 1a5889bb5c..0866c2f5ab 100644 --- a/src/sonic-host-services/tests/hostcfgd/mock_configdb.py +++ b/src/sonic-host-services/tests/common/mock_configdb.py @@ -5,7 +5,7 @@ class MockConfigDb(object): STATE_DB = None CONFIG_DB = None - def __init__(self): + def __init__(self, **kwargs): pass @staticmethod diff --git a/src/sonic-host-services/tests/hostcfgd/hostcfgd_test.py b/src/sonic-host-services/tests/hostcfgd/hostcfgd_test.py index c6d73d42da..52737df91c 100644 --- a/src/sonic-host-services/tests/hostcfgd/hostcfgd_test.py +++ b/src/sonic-host-services/tests/hostcfgd/hostcfgd_test.py @@ -7,7 +7,7 @@ from sonic_py_common.general import load_module_from_source from unittest import TestCase, mock from .test_vectors import HOSTCFGD_TEST_VECTOR -from .mock_configdb import MockConfigDb +from tests.common.mock_configdb import MockConfigDb swsscommon.swsscommon.ConfigDBConnector = MockConfigDb