diff --git a/platform/mellanox/mlnx-platform-api/tests/test_modules_mgmt.py b/platform/mellanox/mlnx-platform-api/tests/test_modules_mgmt.py index 7cf1dc8ceaa6..e18562fe0a43 100644 --- a/platform/mellanox/mlnx-platform-api/tests/test_modules_mgmt.py +++ b/platform/mellanox/mlnx-platform-api/tests/test_modules_mgmt.py @@ -15,13 +15,10 @@ # limitations under the License. # -import logging import os import queue import sys -import syslog import threading -import time import types import unittest @@ -35,141 +32,18 @@ modules_path = os.path.dirname(test_path) sys.path.insert(0, modules_path) -from sonic_platform import utils -import sonic_platform.chassis -from sonic_platform.chassis import Chassis from sonic_platform.device_data import DeviceDataManager from sonic_py_common import device_info from sonic_platform import modules_mgmt from sonic_platform.modules_mgmt import ModulesMgmtTask -from sonic_py_common.logger import Logger from sonic_platform_base.sonic_xcvr.api.public.cmis import CmisApi -from sonic_platform_base.sonic_xcvr.api.public.c_cmis import CCmisApi from sonic_platform_base.sonic_xcvr.xcvr_eeprom import XcvrEeprom from sonic_platform_base.sonic_xcvr.codes.public.cmis import CmisCodes from sonic_platform_base.sonic_xcvr.mem_maps.public.cmis import CmisMemMap from sonic_platform_base.sonic_xcvr.fields import consts -sonic_platform.chassis.extract_RJ45_ports_index = mock.MagicMock(return_value=[]) - -logger = logging.getLogger() -logger.level = logging.DEBUG - - -class LoggerMock(object): - """ - Logger class for SONiC Python applications - """ - LOG_FACILITY_DAEMON = syslog.LOG_DAEMON - LOG_FACILITY_USER = syslog.LOG_USER - - LOG_OPTION_NDELAY = syslog.LOG_NDELAY - LOG_OPTION_PID = syslog.LOG_PID - - LOG_PRIORITY_ERROR = syslog.LOG_ERR - LOG_PRIORITY_WARNING = syslog.LOG_WARNING - LOG_PRIORITY_NOTICE = syslog.LOG_NOTICE - LOG_PRIORITY_INFO = syslog.LOG_INFO - LOG_PRIORITY_DEBUG = syslog.LOG_DEBUG - - DEFAULT_LOG_FACILITY = LOG_FACILITY_USER - DEFAULT_LOG_OPTION = LOG_OPTION_NDELAY - - #syslog_to_logging_prio = { LOG_PRIORITY_INFO : logger.info} - - def __init__(self, log_identifier=None, log_facility=DEFAULT_LOG_FACILITY, log_option=DEFAULT_LOG_OPTION - , also_print_to_console=True): - self._syslog = syslog - - if log_identifier is None: - log_identifier = os.path.basename(sys.argv[0]) - - # Initialize syslog - self._syslog.openlog(ident=log_identifier, logoption=log_option, facility=log_facility) - - # Set the default minimum log priority to LOG_PRIORITY_NOTICE - self.set_min_log_priority(self.LOG_PRIORITY_NOTICE) - - self.also_print_to_console = also_print_to_console - - - def __del__(self): - self._syslog.closelog() - - # - # Methods for setting minimum log priority - # - - def set_min_log_priority(self, priority): - """ - Sets the minimum log priority level to . All log messages - with a priority lower than will not be logged - - Args: - priority: The minimum priority at which to log messages - """ - self._min_log_priority = priority - - def set_min_log_priority_error(self): - """ - Convenience function to set minimum log priority to LOG_PRIORITY_ERROR - """ - self.set_min_log_priority(self.LOG_PRIORITY_ERROR) - - def set_min_log_priority_warning(self): - """ - Convenience function to set minimum log priority to LOG_PRIORITY_WARNING - """ - self.set_min_log_priority(self.LOG_PRIORITY_WARNING) - - def set_min_log_priority_notice(self): - """ - Convenience function to set minimum log priority to LOG_PRIORITY_NOTICE - """ - self.set_min_log_priority(self.LOG_PRIORITY_NOTICE) - - def set_min_log_priority_info(self): - """ - Convenience function to set minimum log priority to LOG_PRIORITY_INFO - """ - self.set_min_log_priority(self.LOG_PRIORITY_INFO) - - def set_min_log_priority_debug(self): - """ - Convenience function to set minimum log priority to LOG_PRIORITY_DEBUG - """ - self.set_min_log_priority(self.LOG_PRIORITY_DEBUG) - - # - # Methods for logging messages - # - - def log(self, priority, msg, also_print_to_console=True): - if self._min_log_priority >= priority: - # Send message to syslog - self._syslog.syslog(priority, msg) - - # Send message to console - if also_print_to_console: - logger.info(msg) - print(msg) - - def log_error(self, msg, also_print_to_console=False): - self.log(self.LOG_PRIORITY_ERROR, msg, also_print_to_console) - - def log_warning(self, msg, also_print_to_console=False): - self.log(self.LOG_PRIORITY_WARNING, msg, also_print_to_console) - - def log_notice(self, msg, also_print_to_console=False): - self.log(self.LOG_PRIORITY_NOTICE, msg, also_print_to_console) - - def log_info(self, msg, also_print_to_console=True): - self.log(self.LOG_PRIORITY_INFO, msg, also_print_to_console) - print(msg) - - def log_debug(self, msg, also_print_to_console=False): - self.log(self.LOG_PRIORITY_DEBUG, msg, also_print_to_console) +TESTED = False def _mock_sysfs_file_content(): return { @@ -190,7 +64,10 @@ def _mock_sysfs_file_content(): modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("2"): "0", modules_mgmt.SYSFS_INDEPENDENT_FD_HW_RESET: "", modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT: "48", - modules_mgmt.SYSFS_INDEPENDENT_FD_FW_CONTROL: "", + modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"): "1", + modules_mgmt.SYSFS_INDEPENDENT_FD_FW_CONTROL.format("0"): "1", + modules_mgmt.SYSFS_INDEPENDENT_FD_FW_CONTROL.format("1"): "1", + modules_mgmt.SYSFS_INDEPENDENT_FD_FW_CONTROL.format("2"): "1", modules_mgmt.SYSFS_LEGACY_FD_PRESENCE: "1", modules_mgmt.PROC_CMDLINE: "" } @@ -199,47 +76,82 @@ def _mock_sysfs_file_content(): mock_file_content = _mock_sysfs_file_content() -def mock_read_str_from_file(file_path, **kwargs): - return mock_file_content[file_path] - - -def mock_write_file(file_path, content, **kwargs): - mock_file_content[file_path] = content - class MockPoller: - def __init__(self, modules_mgmt_task_stopping_event): + def __init__(self, modules_mgmt_task_stopping_event, modules_mgmt_thrd=None, num_of_ports=3, port_plug_out=False + , feature_enabled=True, warm_reboot=False, port_plug_in=False, check_ports=True): self.fds_dict = {} self.poller_count = 0 self.modules_mgmt_task_stopping_event = modules_mgmt_task_stopping_event + self.modules_mgmt_thrd = modules_mgmt_thrd + self.num_of_ports = num_of_ports + self.port_plug_out = port_plug_out + self.port_plug_in = port_plug_in + self.feature_enabled = feature_enabled + self.warm_reboot = warm_reboot + self.check_ports = check_ports def register(self, fd, attrs): self.fds_dict[fd.fileno()] = fd assert fd.fileno() in self.fds_dict - print(f'test registered port fd {fd}') + + def unregister(self, fd): + if fd.fileno() in self.fds_dict.keys(): + del self.fds_dict[fd.fileno()] + assert fd.fileno() not in self.fds_dict.keys() def poll(self, timeout=1000): + global TESTED # when simulating port plug out or plug in need to change both presence and power_good sysfs self.poller_count += 1 - print(f'test polling iteration {self.poller_count}') - if 9 == self.poller_count: - # return first fd registered with some made up event number 870 - fd_to_return = list(self.fds_dict.keys())[0] - fd = self.fds_dict[fd_to_return] - print(f'test MockPoller poll calling {fd}.set_file_int_content with value 0') - print(f'fd {fd} fd.name {fd.name} fd.fileno() {fd.fileno()} dir {fd.__dir__}') - fd.set_file_int_content(0) - fd.set_bla(0) - event_to_return = 870 - print(f'test polling returning fd and event {fd_to_return}, {event_to_return} on iteration {self.poller_count}') - return [(fd_to_return,event_to_return)] - else: - # sleep_time = timeout/1000 - # print(f'test polling sleeping {sleep_time} seconds ...') - # time.sleep(sleep_time) + if self.check_ports: + if 1 == self.poller_count: + if self.port_plug_out: + # return first fd registered with some made up event number 870 + fd_to_return = list(self.fds_dict.keys())[0] + fd = self.fds_dict[fd_to_return] + fd.set_file_int_content(0) + event_to_return = 870 + return [(fd_to_return, event_to_return)] + elif 2 == self.poller_count: + if self.port_plug_in: + # return first fd registered with some made up event number 870 + fd_to_return = list(self.fds_dict.keys())[0] + fd = self.fds_dict[fd_to_return] + fd.set_file_int_content(1) + event_to_return = 871 + return [(fd_to_return, event_to_return)] + elif 7 == self.poller_count: + ports_to_test = self.num_of_ports if (not self.port_plug_out or not self.feature_enabled or self.warm_reboot)\ + else self.num_of_ports * 2 + for i in range(ports_to_test): + # when feature is enabled, power_good sysfs is also registered for cmis non-flat memory cables + port_to_test = i if not self.feature_enabled else int(i / 2) + assert self.modules_mgmt_thrd.sfp_port_dict_initial[port_to_test].port_num == port_to_test + assert self.modules_mgmt_thrd.sfp_port_dict_initial[ + port_to_test].initial_state == modules_mgmt.STATE_HW_NOT_PRESENT + if self.feature_enabled: + module_obj = self.modules_mgmt_thrd.fds_mapping_to_obj[list(self.fds_dict.keys())[i]][ + 'module_obj'] + assert module_obj.port_num == port_to_test + if not self.warm_reboot: + if not self.port_plug_out: + assert module_obj.final_state == modules_mgmt.STATE_SW_CONTROL + else: + assert module_obj.final_state == modules_mgmt.STATE_HW_NOT_PRESENT + else: + if not self.port_plug_out: + assert module_obj.final_state == modules_mgmt.STATE_HW_PRESENT + elif self.port_plug_out and self.port_plug_in: + assert module_obj.final_state == modules_mgmt.STATE_FW_CONTROL + else: + assert module_obj.final_state == modules_mgmt.STATE_HW_NOT_PRESENT + TESTED = True if 10 == self.poller_count: + assert len(self.modules_mgmt_thrd.sfp_port_dict_initial) == self.num_of_ports + assert self.modules_mgmt_thrd.is_supported_indep_mods_system == self.feature_enabled self.modules_mgmt_task_stopping_event.set() - return [] + return [] class MockOpenNew: @@ -249,21 +161,19 @@ def __init__(self, name='', file_no=190, indep_mode=True): self.file_no = file_no self.indep_mode = indep_mode self.retint = None + self.seek_cursor = False + self.curr = 0 def read(self): if self.fileno() in [99]: return "S" else: - print(f'test mock_open_new reading file content') - if self.retint: - print(f'test mock_open_new returning file content {retint}') - return self.retint + if self.retint is not None: + return str(self.retint) else: - print(f'test mock_open_new returning {_mock_sysfs_file_content()[self.name]}') - return _mock_sysfs_file_content()[self.name] + return mock_file_content[self.name] def readline(self): - print(f'reading line fd file_no {self.fileno} fileno() {self.fileno()} self.indep_mode {self.indep_mode}') if self.fileno() in [99]: if self.indep_mode: return "SAI_INDEPENDENT_MODULE_MODE=1" @@ -275,60 +185,75 @@ def readline(self): def fileno(self): return self.file_no + def seek(self, seek_val): + self.curr = seek_val + + def close(self): + pass + + def write(self, write_val): + self.set_file_int_content(write_val) + def set_file_int_content(self, retint): - print(f'test mock_open_new setting file content {retint}') - self.retint = retint + self.retint = str(retint) + mock_file_content[self.name] = str(retint) - # def __enter__(self): - # print(f"enter MockOpenNew name {self.name} file_no {self.file_no}") - # - # def __exit__(self): - # print(f"exit MockOpenNew name {self.name} file_no {self.file_no}") + def __enter__(self): + return self + + def __exit__(self, filename, *args, **kwargs): + pass class MockPollerStopEvent: - def __init__(self, modules_mgmt_task_stopping_event, modules_mgmt_thrd=None, feature_enabled=True): + def __init__(self, modules_mgmt_task_stopping_event, modules_mgmt_thrd=None, num_of_ports=3, feature_enabled=True + , check_ports=True, ports_connected=True, ports_error=False, fw_controlled_ports=False): self.fds_dict = {} - self.modules_mgmt_thrd = modules_mgmt_thrd self.modules_mgmt_task_stopping_event = modules_mgmt_task_stopping_event + self.modules_mgmt_thrd = modules_mgmt_thrd + self.num_of_ports = num_of_ports self.feature_enabled = feature_enabled + self.check_ports = check_ports + self.ports_connected = ports_connected + self.ports_error = ports_error + self.fw_controlled_ports = fw_controlled_ports + self.tested = False def register(self, fd, attrs): self.fds_dict[fd.fileno()] = 1 & attrs - #assert fd.fileno() in [0, 1, 2] assert fd.fileno() in self.fds_dict - print(f'test registered port fd {fd}') def poll(self, timeout=1000): - print(f'test starting poll tests') - assert len(self.modules_mgmt_thrd.sfp_port_dict_initial) == 3 + assert len(self.modules_mgmt_thrd.sfp_port_dict_initial) == self.num_of_ports assert self.modules_mgmt_thrd.is_supported_indep_mods_system == self.feature_enabled - #try: - if True: - print(f'test starting ports tests') - for i in range(3 if not self.feature_enabled else 6): - print(f'test port {i} starting tests') + if self.check_ports: + ports_to_test = self.num_of_ports if (not self.feature_enabled or not self.ports_connected or self.ports_error + or self.fw_controlled_ports) else self.num_of_ports * 2 + for i in range(ports_to_test): # when feature is enabled, power_good sysfs is also registered for cmis non-flat memory cables - port_to_test = i if not self.feature_enabled else int(i / 2) + port_to_test = i if (not self.feature_enabled or not self.ports_connected or self.ports_error + or self.fw_controlled_ports) else int(i / 2) assert self.modules_mgmt_thrd.sfp_port_dict_initial[port_to_test].port_num == port_to_test assert self.modules_mgmt_thrd.sfp_port_dict_initial[port_to_test].initial_state == modules_mgmt.STATE_HW_NOT_PRESENT - if True:#not self.feature_enabled: - print(f'test getting module_obj for port {i}') - module_obj = self.modules_mgmt_thrd.fds_mapping_to_obj[list(self.fds_dict.keys())[i]]['module_obj'] - assert module_obj.port_num == port_to_test - #assert module_obj.current_state == modules_mgmt.STATE_FW_CONTROL - #assert module_obj.final_state == modules_mgmt.STATE_FW_CONTROL - print(f'test port {i} final_state {module_obj.final_state}') - if self.feature_enabled: - assert module_obj.final_state == modules_mgmt.STATE_SW_CONTROL + module_obj = self.modules_mgmt_thrd.fds_mapping_to_obj[list(self.fds_dict.keys())[i]]['module_obj'] + assert module_obj.port_num == port_to_test + if self.ports_error: + assert module_obj.final_state == modules_mgmt.STATE_ERROR_HANDLER + else: + if self.ports_connected: + if self.feature_enabled: + if self.fw_controlled_ports: + assert module_obj.final_state == modules_mgmt.STATE_FW_CONTROL + else: + assert module_obj.final_state == modules_mgmt.STATE_SW_CONTROL + else: + assert module_obj.final_state == modules_mgmt.STATE_HW_PRESENT else: - assert module_obj.final_state == modules_mgmt.STATE_HW_PRESENT - #module_fd = self.fds_mapping_to_obj[fd]['fd'] - #fd_name = self.fds_mapping_to_obj[fd]['fd_name'] - # except IndexError as e: - # print(f'exception in test {e} on i {i}') + assert module_obj.final_state == modules_mgmt.STATE_HW_NOT_PRESENT self.modules_mgmt_task_stopping_event.set() + global TESTED + TESTED = True return [] @@ -343,7 +268,7 @@ def _mock_is_file_indep_mode_disabled_content(): modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"): True, modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1"): True, modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2"): True, - '//usr/share/sonic/platform/ACS-MSN4700/sai.profile' : True + '//usr/share/sonic/platform/ACS-MSN4700/sai.profile' : True } @@ -362,6 +287,7 @@ def _mock_is_file_indep_mode_enabled_content(): modules_mgmt.SYSFS_INDEPENDENT_FD_HW_RESET: True, modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT: True, modules_mgmt.SYSFS_INDEPENDENT_FD_FW_CONTROL: True, + modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"): True, modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("0"): True, modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("1"): True, modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("2"): True, @@ -382,7 +308,7 @@ def mock_is_file_indep_mode_enabled(file_path, **kwargs): return mock_is_file_indep_mode_enabled_content[file_path] -def mock_read_int_from_file_new_no_self(filename, *args): +def mock_read_int_from_file(filename, *args): return_dict = { modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0") : 1, modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1") : 1, @@ -393,7 +319,6 @@ def mock_read_int_from_file_new_no_self(filename, *args): class MockXcvrEeprom(): - def __init__(self, is_flat_memory, mem_map): self.is_flat_memory = is_flat_memory self.mem_map = mem_map @@ -405,75 +330,55 @@ def is_flat_memory(self): return self.is_flat_memory def read(self, field): - print(f'test MockXcvrEeprom read field {field}') if consts.FLAT_MEM_FIELD == field: return 0 if self.is_flat_memory else 1 else: return 0 -class MockXcvrapi(): - # def __new__(cls, *args, **kwargs): - # return mock.Mock(autospec=cls) - +class MockXcvrapi: def __init__(self, is_cmis_api=True, is_flat_memory_bool=False): - print(f'test MockXcvrapi init is_cmis_api {is_cmis_api} is_flat_memory_bool {is_flat_memory_bool}') self.is_cmis_api = is_cmis_api self.is_flat_memory_bool = is_flat_memory_bool - self.xcvr_eeprom = MagicMock(autospec=XcvrEeprom, return_value=MockXcvrEeprom(False, CmisMemMap(CmisCodes))) + self.xcvr_eeprom = MagicMock(autospec=XcvrEeprom, return_value=MockXcvrEeprom(is_flat_memory_bool, CmisMemMap(CmisCodes))) def is_flat_memory(self): - print(f'test returning for is_flat_memory {self.is_flat_memory_bool}') return self.is_flat_memory_bool def xcvr_eeprom(self): - print(f'test returning xcvr_eeprom {self.xcvr_eeprom}') return self.xcvr_eeprom class MockSFPxcvrapi: - def __init__(self, xcvr_api_is_cmis_api=True, xcvr_eeprom_is_flat_memory=False): - print(f'test MockSFPxcvrapi init xcvr_api_is_cmis_api {xcvr_api_is_cmis_api} xcvr_eeprom_is_flat_memory {xcvr_eeprom_is_flat_memory}') self.xcvr_api = Mock(spec=CmisApi(MockXcvrEeprom(False, CmisMemMap(CmisCodes))), return_value=MockXcvrapi(xcvr_api_is_cmis_api, xcvr_eeprom_is_flat_memory)) self.xcvr_api_is_cmis_api = xcvr_api_is_cmis_api self.xcvr_eeprom_is_flat_memory = xcvr_eeprom_is_flat_memory self.xcvr_api.is_flat_memory = types.MethodType(self.is_flat_memory, self) - #__enter__.return_value - #self.xcvr_api.is_flat_memory = self.is_flat_memory() def get_xcvr_api(self): return self.xcvr_api def is_flat_memory(self, ref): - print(f'test MockSFPxcvrapi returning is_flat_memory {self.xcvr_eeprom_is_flat_memory}') return self.xcvr_eeprom_is_flat_memory -mock_sfp_all_ports_cmis_api = { - 0: MockSFPxcvrapi(), - 1: MockSFPxcvrapi(), - 2: MockSFPxcvrapi() -} - - -def mock_sfp(port, *args, **kwargs): - print(f'returning mock sfp for port {port}') - return mock_sfp_all_ports_cmis_api[port] - - def check_power_cap(port, module_sm_obj): pass + class TestModulesMgmt(unittest.TestCase): """Test class to test modules_mgmt.py. The test cases covers: - 1. cables detection for all 32 ports + 1. cables detection for 1 to 3 32 ports - feature disabled / enabled / poller 2. cable disconnection - plug out 3. cable reconnection - plug in + 4. warm reboot normal flow with FW ports + 5. warm reboot flow with FW ports plugged out + 6. warm reboot flow with FW ports plugged out and then plugged in (stays FW controlled, no SFP mock change) + 7. test 32 FW controlled (non cmis flat mem) cables powered off + 8. test 32 SW controlled (cmis active non flat mem) cables powered off """ - fds_and_events = {'90': '1', '91': '2', '92': '3'} - def _mock_sysfs_file_content(self): return { modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE : "1", @@ -488,74 +393,44 @@ def _mock_sysfs_file_content(self): modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("0"): "0" } - def mock_open_new(self, file_name, *args, **kwargs): - return_dict = { - (modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"), 'r') : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"), 0), - (modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1"), 'r') : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1"), 1), - (modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2"), 'r') : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2"), 2), - ('//usr/share/sonic/platform/ACS-MSN4700/sai.profile', 'r') : MockOpenNew('//usr/share/sonic/platform/ACS-MSN4700/sai.profile', 99) - } - return return_dict[file_name] - def mock_open_builtin(self, file_name, feature_enabled=True): return_dict = { - (modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"), 'r') : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"), 0), - (modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1"), 'r') : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1"), 1), - (modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2"), 'r') : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2"), 2), + (modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"), 'r') : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"), 100), + (modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1"), 'r') : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1"), 101), + (modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2"), 'r') : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2"), 102), '//usr/share/sonic/platform/ACS-MSN4700/sai.profile' : MockOpenNew('//usr/share/sonic/platform/ACS-MSN4700/sai.profile', 99, feature_enabled), - modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0") : MockOpenNew(name=modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"), file_no=0), - modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1") : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1"), 1), - modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2") : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2"), 2), - #modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("0"): MagicMock(return_value=MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("0"), 0)), + modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0") : MockOpenNew(name=modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"), file_no=100), + modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1") : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1"), 101), + modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2") : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2"), 102), modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("0"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("0"), 0), modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("1"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("1"), 1), modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("2"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("2"), 2), - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("0"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("0"), 50), - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("1"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("1"), 51), - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("2"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("2"), 52), - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("0"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("0"), 90), - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("1"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("1"), 91), - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("2"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("2"), 92), - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("0"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("0"), 100), - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("1"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("1"), 101), - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("2"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("2"), 102), - modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("0"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("0"), 112), - modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("1"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("1"), 112), - modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("2"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("2"), 112), + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("0"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("0"), 200), + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("1"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("1"), 201), + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("2"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("2"), 202), + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("0"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("0"), 300), + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("1"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("1"), 301), + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("2"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("2"), 302), + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("0"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("0"), 500), + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("1"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("1"), 501), + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("2"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("2"), 502), + modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("0"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("0"), 602), + modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("1"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("1"), 602), + modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("2"): MockOpenNew(modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("2"), 602), modules_mgmt.PROC_CMDLINE: MockOpenNew(modules_mgmt.PROC_CMDLINE, 200) } return return_dict[file_name] - def mock_open_builtin_feature_enabled(self, file_name): - return_dict = { - (modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"), 'r') : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"), 0), - (modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1"), 'r') : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1"), 1), - (modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2"), 'r') : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2"), 2), - '//usr/share/sonic/platform/ACS-MSN4700/sai.profile' : MockOpenNew('//usr/share/sonic/platform/ACS-MSN4700/sai.profile', 99), - modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0") : MockOpenNew(name=modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"), file_no=0), - modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1") : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1"), 1), - modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2") : MockOpenNew(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2"), 2) - } - return return_dict[file_name] - - def mock_open_new_side_effect_feature_disabled(self, filename, *args, **kwargs): mock_context = MagicMock() - #mock_context.__enter__.return_value = self.mock_open_builtin(filename, args, kwargs) mock_context.__enter__.return_value = self.mock_open_builtin(filename, False) mock_context.__exit__.return_value = False - mock_context.return_value.__enter__.return_value.readline.return_value = "SAI_INDEPENDENT_MODULE_MODE=1" - mock_context.return_value.readline.return_value = "SAI_INDEPENDENT_MODULE_MODE=1" return mock_context def mock_open_new_side_effect_feature_enabled(self, filename, *args, **kwargs): mock_context = MagicMock() - #mock_context.__enter__.return_value = self.mock_open_builtin(filename, args, kwargs) mock_context.__enter__.return_value = self.mock_open_builtin(filename) - #mock_context.__enter__.return_value = self.mock_open_builtin_feature_enabled(filename) mock_context.__exit__.return_value = False - #mock_context.return_value.__enter__.return_value.readline.return_value = "SAI_INDEPENDENT_MODULE_MODE=1" - #mock_context.return_value.readline.return_value = "SAI_INDEPENDENT_MODULE_MODE=1" return mock_context def mock_open_new_side_effect_poller_test(self, filename, *args, **kwargs): @@ -565,223 +440,454 @@ def mock_open_new_side_effect_poller_test(self, filename, *args, **kwargs): mock_context.__exit__.return_value = False return mock_context else: - #return MagicMock(return_value=MockOpenNew(filename, self.fd_number_by_fd_name_dict[filename])) mock_context = MagicMock() mock_open_new = MockOpenNew(filename, self.fd_number_by_fd_name_dict[filename]) mock_context.return_value = mock_open_new - #mock_open_new.return_value.read = mock_open_new.read - #mock_context.return_value.__enter__ = MockOpenNew(filename, self.fd_number_by_fd_name_dict[filename]) mock_context.__enter__.return_value = mock_open_new mock_context.__exit__.return_value = False - if 'present' in filename or 'power' in filename or 'freq': + if 'hw_present' in filename or 'power_on' in filename or 'freq' in filename or 'control' in filename: return mock_context else: return mock_context.return_value + def mock_open_new_side_effect_warm_reboot(self, filename, *args, **kwargs): + if filename in ['//usr/share/sonic/platform/ACS-MSN4700/sai.profile']: + mock_context = MagicMock() + mock_context.__enter__.return_value = MockOpenNew(filename, 99) + mock_context.__exit__.return_value = False + return mock_context + else: + mock_open_new = MockOpenNew(filename, self.fd_number_by_fd_name_dict[filename]) + return mock_open_new + - @classmethod + #@classmethod def setup_class(cls): os.environ["MLNX_PLATFORM_API_UNIT_TESTING"] = "1" - #cls.mock_file_content = cls._mock_sysfs_file_content() cls.fd_number_by_fd_name_dict = { - modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0") : 0, - modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1") : 1, - modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2") : 2, + modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0") : 100, + modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1") : 101, + modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2") : 102, '//usr/share/sonic/platform/ACS-MSN4700/sai.profile' : 99, modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("0") : 0, modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("1") : 1, modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("2") : 2, - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("0") : 50, - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("1") : 51, - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("2") : 52, - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("0") : 90, - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("1") : 91, - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("2") : 92, - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("0") : 100, - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("1") : 101, - modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("2") : 102, - modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("0") : 110, - modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("1") : 111, - modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("2") : 112, + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("0") : 200, + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("1") : 201, + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("2") : 202, + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("0") : 300, + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("1") : 301, + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("2") : 302, + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("0") : 500, + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("1") : 501, + modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("2") : 502, + modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("0") : 600, + modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("1") : 601, + modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("2") : 602, + modules_mgmt.SYSFS_INDEPENDENT_FD_FW_CONTROL.format("0") : 700, + modules_mgmt.SYSFS_INDEPENDENT_FD_FW_CONTROL.format("1") : 701, + modules_mgmt.SYSFS_INDEPENDENT_FD_FW_CONTROL.format("2") : 702, modules_mgmt.PROC_CMDLINE : 200 } + # mock the directory holding relevant sai.profile + device_info.get_paths_to_platform_and_hwsku_dirs = mock.MagicMock(return_value=('', '/usr/share/sonic/platform/ACS-MSN4700')) - def mock_read_int_from_file(self, file_path, *args): - return self._mock_sysfs_file_content[file_path] - #return self._mock_sysfs_file_content[args] - - def mock_write_file(self, file_path, content, **kwargs): - self._mock_sysfs_file_content[file_path] = content - - def mock_read_int_from_file_new(self, filename, *args): - return_dict = { - modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0") : 1, - modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1") : 1, - modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2") : 1 - } - - return return_dict[filename] - - - # builtin_open = open # save the unpatched version - # - # def mock_open(*args, **kwargs): - # if 'present' in args[0]: - # # mocked open for path "foo" - # return mock.mock_open(read_data="bar")(*args, **kwargs) - # # unpatched version for every other path - # return builtin_open(*args, **kwargs) - - @mock.patch('sonic_platform.device_data.DeviceDataManager.get_sfp_count', MagicMock(return_value=3)) - @patch('sonic_py_common.logger.Logger', Mock(return_value=LoggerMock)) + @patch('sonic_platform.device_data.DeviceDataManager.get_sfp_count', MagicMock(return_value=3)) @patch('os.path.isfile', MagicMock(side_effect=mock_is_file_indep_mode_disabled)) - @patch('sonic_platform.utils.read_int_from_file', MagicMock(side_effect=mock_read_int_from_file_new_no_self)) + @patch('sonic_platform.utils.read_int_from_file', MagicMock(side_effect=mock_read_int_from_file)) @patch('builtins.open', spec=open) def test_mdf_all_ports_feature_disabled(self, mock_open): + mock_open.side_effect = self.mock_open_new_side_effect_feature_disabled + global TESTED + TESTED = False + num_of_tested_ports = DeviceDataManager.get_sfp_count() + assert num_of_tested_ports == 3 - #stream_handler = logging.StreamHandler(sys.stdout) - #logger.addHandler(stream_handler) - try: - chassis = Chassis() - chassis.modules_mgmt_thread.is_alive = MagicMock(return_value=True) - mock_file_content = self._mock_sysfs_file_content() - - num_of_tested_ports = DeviceDataManager.get_sfp_count() - assert num_of_tested_ports == 3 - - device_info.get_paths_to_platform_and_hwsku_dirs = mock.MagicMock(return_value=('', '/usr/share/sonic/platform/ACS-MSN4700')) - modules_mgmt_task_stopping_event = threading.Event() - modules_changes_queue = queue.Queue() - modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=modules_mgmt_task_stopping_event, - q=modules_changes_queue) - modules_mgmt_thrd.logger = logger - thrd_stream_handler = logging.StreamHandler(sys.stdout) - modules_mgmt_thrd.logger.addHandler(thrd_stream_handler) - Logger.level = logging.DEBUG - #logger_logger = Logger() - #logger_logger.addHandler(thrd_stream_handler) - #thrd_logger = ModulesMgmtTask.logger.getLogger() - #thrd_stream_handler = logging.StreamHandler(sys.stdout) - #thrd_logger.addHandler(thrd_stream_handler) - with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(modules_mgmt_task_stopping_event - , modules_mgmt_thrd, False))): - #with caplog.at_level(logging.DEBUG): - #with pytest.raises(AttributeError): - # mdf_logger = logging.getLogger('sonic_platform.modules_mgmt') - # with mock.patch.object(mdf_logger, 'debug') as mock_debug: - assert modules_mgmt_thrd.sfp_port_dict_initial == {} - assert modules_mgmt_thrd.is_supported_indep_mods_system == False - print('starting') - mock_open.side_effect = self.mock_open_new_side_effect_feature_disabled - #modules_mgmt_thrd.start() - modules_mgmt_thrd.run() - print('finishing') - #modules_mgmt_thrd.join() - sys.stdout.flush() - finally: - pass - + # start modules_mgmt thread and the test in poller part + modules_mgmt_task_stopping_event = threading.Event() + modules_changes_queue = queue.Queue() + modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=modules_mgmt_task_stopping_event, + q=modules_changes_queue) + with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(modules_mgmt_task_stopping_event + , modules_mgmt_thrd, feature_enabled=False))): + assert modules_mgmt_thrd.sfp_port_dict_initial == {} + assert modules_mgmt_thrd.is_supported_indep_mods_system == False + modules_mgmt_thrd.run() + # a check that modules mgmt thread ran and got into the poller part + assert TESTED - @mock.patch('sonic_platform.device_data.DeviceDataManager.get_sfp_count', MagicMock(return_value=3)) + @patch('sonic_platform.device_data.DeviceDataManager.get_sfp_count', MagicMock(return_value=3)) @patch('os.path.isfile', MagicMock(side_effect=mock_is_file_indep_mode_enabled)) @patch('builtins.open', spec=open) def test_mdf_all_ports_feature_enabled(self, mock_open): - chassis = Chassis() - chassis.modules_mgmt_thread.is_alive = MagicMock(return_value=True) - mock_file_content = self._mock_sysfs_file_content() - - def mock_read_int_from_file(file_path, **kwargs): - return mock_file_content[file_path] - - def mock_write_file(file_path, content, **kwargs): - mock_file_content[file_path] = content - - utils.read_str_from_file = mock_read_str_from_file - utils.write_file = mock_write_file - + mock_open.side_effect = self.mock_open_new_side_effect_feature_enabled + global TESTED + TESTED = False num_of_tested_ports = DeviceDataManager.get_sfp_count() assert num_of_tested_ports == 3 - device_info.get_paths_to_platform_and_hwsku_dirs = mock.MagicMock(return_value=('', '/usr/share/sonic/platform/ACS-MSN4700')) + # start modules_mgmt thread and the test in poller part modules_mgmt_task_stopping_event = threading.Event() modules_changes_queue = queue.Queue() modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=modules_mgmt_task_stopping_event, q=modules_changes_queue) assert modules_mgmt_thrd.sfp_port_dict_initial == {} - mock_open.side_effect = self.mock_open_new_side_effect_feature_enabled - with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(modules_mgmt_task_stopping_event , modules_mgmt_thrd))): with patch('sonic_platform.sfp.SFP', MagicMock(return_value=MockSFPxcvrapi())): modules_mgmt_thrd.check_power_cap = check_power_cap modules_mgmt_thrd.run() - #modules_mgmt_thrd.start() - #modules_mgmt_thrd.join() + # a check that modules mgmt thread ran and got into the poller part + assert TESTED @patch('os.path.isfile', MagicMock(side_effect=mock_is_file_indep_mode_enabled)) @patch('builtins.open', spec=open) - #@patch('builtins.open', new=mock_open) @patch('sonic_platform.sfp.SFP', MagicMock(return_value=MockSFPxcvrapi())) def test_modules_mgmt_poller_events_3_ports(self, mock_open): - mock_file_content = self._mock_sysfs_file_content() + mock_open.side_effect = self.mock_open_new_side_effect_poller_test + mock_file_content[modules_mgmt.PROC_CMDLINE] = '' + global TESTED + TESTED = False + DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=3) + num_of_tested_ports = DeviceDataManager.get_sfp_count() + assert num_of_tested_ports == 3 - def mock_read_int_from_file(file_path, **kwargs): - return mock_file_content[file_path] + # start modules_mgmt thread and the test in poller part + modules_mgmt_task_stopping_event = threading.Event() + modules_changes_queue = queue.Queue() + modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=modules_mgmt_task_stopping_event + , q=modules_changes_queue) + with patch('select.poll', MagicMock(return_value=MockPoller(modules_mgmt_task_stopping_event, modules_mgmt_thrd))): + modules_mgmt_thrd.check_power_cap = check_power_cap + modules_mgmt_thrd.run() + # a check that modules mgmt thread ran and got into the poller part + assert TESTED - def mock_write_file(file_path, content, **kwargs): - mock_file_content[file_path] = content + @patch('os.path.isfile', MagicMock(side_effect=mock_is_file_indep_mode_enabled)) + @patch('builtins.open', spec=open) + @patch('sonic_platform.sfp.SFP', MagicMock(return_value=MockSFPxcvrapi())) + def test_modules_mgmt_poller_events_single_port(self, mock_open): + mock_open.side_effect = self.mock_open_new_side_effect_poller_test + global TESTED + TESTED = False + DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=1) + num_of_tested_ports = DeviceDataManager.get_sfp_count() + assert num_of_tested_ports == 1 - utils.read_str_from_file = mock_read_str_from_file - utils.write_file = mock_write_file - mock_open.side_effect = self.mock_open_new_side_effect_feature_enabled + # start modules_mgmt thread and the test in poller part + modules_mgmt_task_stopping_event = threading.Event() + modules_changes_queue = queue.Queue() + modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=modules_mgmt_task_stopping_event + , q=modules_changes_queue) + with patch('select.poll', MagicMock(return_value=MockPoller(modules_mgmt_task_stopping_event + , modules_mgmt_thrd, num_of_tested_ports))): + with patch('builtins.open', MagicMock(side_effect=self.mock_open_new_side_effect_poller_test)): + modules_mgmt_thrd.check_power_cap = check_power_cap + modules_mgmt_thrd.run() + # a check that modules mgmt thread ran and got into the poller part + assert TESTED + @patch('os.path.isfile', MagicMock(side_effect=mock_is_file_indep_mode_enabled)) + @patch('builtins.open', spec=open) + @patch('sonic_platform.sfp.SFP', MagicMock(return_value=MockSFPxcvrapi(False, True))) + def test_modules_mgmt_normal_warm_reboot(self, mock_open): + mock_open.side_effect = self.mock_open_new_side_effect_warm_reboot + # mock /proc/cmdline with warm reboot boot type key value + mock_file_content[modules_mgmt.PROC_CMDLINE] = f'{modules_mgmt.CMDLINE_STR_TO_LOOK_FOR}{modules_mgmt.CMDLINE_VAL_TO_LOOK_FOR}' + global TESTED + TESTED = False + DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=1) + num_of_tested_ports = DeviceDataManager.get_sfp_count() + assert num_of_tested_ports == 1 + # set the port to start with FW controlled before warm reboot takes place + mock_file_content[modules_mgmt.SYSFS_INDEPENDENT_FD_FW_CONTROL.format("0")] = "0" - # utils.read_int_from_file = self.mock_read_int_from_file - # utils.write_file = self.mock_write_file + # start modules_mgmt thread and the test in poller part + modules_mgmt_task_stopping_event = threading.Event() + modules_changes_queue = queue.Queue() + modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=modules_mgmt_task_stopping_event, q=modules_changes_queue) + with patch('select.poll', MagicMock(return_value=MockPoller(modules_mgmt_task_stopping_event, modules_mgmt_thrd + , num_of_tested_ports, warm_reboot=True))): + modules_mgmt_thrd.check_power_cap = check_power_cap + modules_mgmt_thrd.run() + # a check that modules mgmt thread ran and got into the poller part + assert TESTED - device_info.get_paths_to_platform_and_hwsku_dirs = mock.MagicMock(return_value=('', '/usr/share/sonic/platform/ACS-MSN4700')) - #with patch("builtins.open", MagicMock(return_value=self.mock_open_new)) as mock_file: - DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=3) + @patch('os.path.isfile', MagicMock(side_effect=mock_is_file_indep_mode_enabled)) + @patch('builtins.open', spec=open) + @patch('sonic_platform.sfp.SFP', MagicMock(return_value=MockSFPxcvrapi(False, True))) + def test_modules_mgmt_plug_out_fw_cable_after_warm_reboot(self, mock_open): + mock_open.side_effect = self.mock_open_new_side_effect_warm_reboot + # mock /proc/cmdline with warm reboot boot type key value + mock_file_content[modules_mgmt.PROC_CMDLINE] = f'{modules_mgmt.CMDLINE_STR_TO_LOOK_FOR}{modules_mgmt.CMDLINE_VAL_TO_LOOK_FOR}' + global TESTED + TESTED = False + DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=1) num_of_tested_ports = DeviceDataManager.get_sfp_count() - assert num_of_tested_ports == 3 + assert num_of_tested_ports == 1 + # set the port to start with FW controlled before warm reboot takes place + mock_file_content[modules_mgmt.SYSFS_INDEPENDENT_FD_FW_CONTROL.format("0")] = "0" + # start modules_mgmt thread and the test in poller part modules_mgmt_task_stopping_event = threading.Event() modules_changes_queue = queue.Queue() - modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=modules_mgmt_task_stopping_event, q=modules_changes_queue) - with patch('select.poll', MagicMock(return_value=MockPoller(modules_mgmt_task_stopping_event))): + modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=modules_mgmt_task_stopping_event + , q=modules_changes_queue) + with patch('select.poll', MagicMock(return_value=MockPoller(modules_mgmt_task_stopping_event + , modules_mgmt_thrd, num_of_tested_ports, port_plug_out=True, warm_reboot=True))): modules_mgmt_thrd.check_power_cap = check_power_cap modules_mgmt_thrd.run() + # a check that modules mgmt thread ran and got into the poller part + assert TESTED @patch('os.path.isfile', MagicMock(side_effect=mock_is_file_indep_mode_enabled)) @patch('builtins.open', spec=open) - @patch('sonic_platform.sfp.SFP', MagicMock(return_value=MockSFPxcvrapi())) - def test_modules_mgmt_poller_events_single_port(self, mock_open): - mock_file_content = self._mock_sysfs_file_content() + @patch('sonic_platform.sfp.SFP', MagicMock(return_value=MockSFPxcvrapi(False, True))) + def test_modules_mgmt_plug_out_plug_in_fw_cable_after_warm_reboot(self, mock_open): + mock_open.side_effect = self.mock_open_new_side_effect_warm_reboot + # mock /proc/cmdline with warm reboot boot type key value + mock_file_content[modules_mgmt.PROC_CMDLINE] = f'{modules_mgmt.CMDLINE_STR_TO_LOOK_FOR}{modules_mgmt.CMDLINE_VAL_TO_LOOK_FOR}' + global TESTED + TESTED = False + DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=1) + num_of_tested_ports = DeviceDataManager.get_sfp_count() + assert num_of_tested_ports == 1 - def mock_read_int_from_file(file_path, **kwargs): - return mock_file_content[file_path] + mock_file_content[modules_mgmt.SYSFS_INDEPENDENT_FD_FW_CONTROL.format("0")] = "0" - def mock_write_file(file_path, content, **kwargs): - mock_file_content[file_path] = content + # start modules_mgmt thread and the test in poller part + modules_mgmt_task_stopping_event = threading.Event() + modules_changes_queue = queue.Queue() + modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=modules_mgmt_task_stopping_event + , q=modules_changes_queue) + with patch('select.poll', MagicMock(return_value=MockPoller(modules_mgmt_task_stopping_event + , modules_mgmt_thrd, num_of_tested_ports, port_plug_out=True, warm_reboot=True, port_plug_in=True))): + modules_mgmt_thrd.check_power_cap = check_power_cap + modules_mgmt_thrd.run() + # a check that modules mgmt thread ran and got into the poller part + assert TESTED - utils.read_str_from_file = mock_read_str_from_file - utils.write_file = mock_write_file + @patch('os.path.isfile', MagicMock(side_effect=mock_is_file_indep_mode_enabled)) + @patch('builtins.open', spec=open) + @patch('sonic_platform.sfp.SFP', MagicMock(return_value=MockSFPxcvrapi(False, True))) + def test_modules_mgmt_no_ports(self, mock_open): mock_open.side_effect = self.mock_open_new_side_effect_poller_test - #mock_open.return_value = MagicMock(return_value=MockOpenNew(filename, 0)) + global TESTED + TESTED = False + DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=0) + num_of_tested_ports = DeviceDataManager.get_sfp_count() + assert num_of_tested_ports == 0 + # start modules_mgmt thread and the test in poller part + modules_mgmt_task_stopping_event = threading.Event() + modules_changes_queue = queue.Queue() + modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=modules_mgmt_task_stopping_event + , q=modules_changes_queue) + with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(modules_mgmt_task_stopping_event + , modules_mgmt_thrd, num_of_tested_ports, check_ports=False))): + modules_mgmt_thrd.check_power_cap = check_power_cap + modules_mgmt_thrd.run() + # a check that modules mgmt thread ran and got into the poller part + assert TESTED + @patch('os.path.isfile', MagicMock(side_effect=mock_is_file_indep_mode_enabled)) + @patch('builtins.open', spec=open) + @patch('sonic_platform.sfp.SFP', MagicMock(return_value=MockSFPxcvrapi(False, True))) + def test_modules_mgmt_ports_disconnected(self, mock_open): + mock_open.side_effect = self.mock_open_new_side_effect_poller_test + global TESTED + TESTED = False + num_of_ports = 3 + DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=num_of_ports) + num_of_tested_ports = DeviceDataManager.get_sfp_count() + assert num_of_tested_ports == num_of_ports - device_info.get_paths_to_platform_and_hwsku_dirs = mock.MagicMock(return_value=('', '/usr/share/sonic/platform/ACS-MSN4700')) - DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=1) + # update hw_present sysfs with value of 0 for each port + for i in range(num_of_tested_ports): + modules_sysfs = modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format(f"{i}") + mock_file_content[modules_sysfs] = "0" + + # start modules_mgmt thread and the test in poller part + modules_mgmt_task_stopping_event = threading.Event() + modules_changes_queue = queue.Queue() + modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=modules_mgmt_task_stopping_event + , q=modules_changes_queue) + with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(modules_mgmt_task_stopping_event + , modules_mgmt_thrd, num_of_tested_ports, ports_connected=False))): + modules_mgmt_thrd.check_power_cap = check_power_cap + modules_mgmt_thrd.run() + # a check that modules mgmt thread ran and got into the poller part + assert TESTED + + @patch('os.path.isfile', MagicMock(side_effect=mock_is_file_indep_mode_enabled)) + @patch('builtins.open', spec=open) + @patch('sonic_platform.sfp.SFP', MagicMock(return_value=MockSFPxcvrapi(False, True))) + def test_modules_mgmt_bad_flows_port_disconnected(self, mock_open): + mock_open.side_effect = self.mock_open_new_side_effect_poller_test + global TESTED + TESTED = False + num_of_ports = 1 + DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=num_of_ports) num_of_tested_ports = DeviceDataManager.get_sfp_count() - assert num_of_tested_ports == 1 + assert num_of_tested_ports == num_of_ports + # update hw_present sysfs with value of 0 for each port + for i in range(num_of_tested_ports): + modules_sysfs = modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format(f"{i}") + mock_file_content[modules_sysfs] = "0" + + # start modules_mgmt thread and the test in poller part modules_mgmt_task_stopping_event = threading.Event() modules_changes_queue = queue.Queue() - modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=modules_mgmt_task_stopping_event, q=modules_changes_queue) - with patch('select.poll', MagicMock(return_value=MockPoller(modules_mgmt_task_stopping_event))): - with patch('builtins.open', MagicMock(side_effect=self.mock_open_new_side_effect_poller_test)): - modules_mgmt_thrd.check_power_cap = check_power_cap - modules_mgmt_thrd.run() + modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=modules_mgmt_task_stopping_event + , q=modules_changes_queue) + with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(modules_mgmt_task_stopping_event + , modules_mgmt_thrd, num_of_tested_ports, ports_connected=False))): + modules_mgmt_thrd.check_power_cap = check_power_cap + modules_mgmt_thrd.run() + # a check that modules mgmt thread ran and got into the poller part + assert TESTED + + @patch('os.path.isfile', MagicMock(side_effect=mock_is_file_indep_mode_enabled)) + @patch('builtins.open', spec=open) + @patch('sonic_platform.sfp.SFP', MagicMock(return_value=MockSFPxcvrapi(False, True))) + def test_modules_mgmt_bad_flows_power_good(self, mock_open): + mock_open.side_effect = self.mock_open_new_side_effect_poller_test + global TESTED + TESTED = False + num_of_ports = 1 + DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=num_of_ports) + num_of_tested_ports = DeviceDataManager.get_sfp_count() + assert num_of_tested_ports == num_of_ports + + # update power_good sysfs with value of 0 for each port + for i in range(num_of_tested_ports): + modules_sysfs = modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format(f"{i}") + mock_file_content[modules_sysfs] = "0" + + # start modules_mgmt thread and the test in poller part + modules_mgmt_task_stopping_event = threading.Event() + modules_changes_queue = queue.Queue() + modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=modules_mgmt_task_stopping_event + , q=modules_changes_queue) + with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(modules_mgmt_task_stopping_event + , modules_mgmt_thrd, num_of_tested_ports, ports_connected=False))): + modules_mgmt_thrd.check_power_cap = check_power_cap + modules_mgmt_thrd.run() + for i in range(num_of_tested_ports): + modules_sysfs = modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format(f"{i}") + mock_file_content[modules_sysfs] = "1" + # a check that modules mgmt thread ran and got into the poller part + assert TESTED + + @patch('os.path.isfile', MagicMock(side_effect=mock_is_file_indep_mode_enabled)) + @patch('builtins.open', spec=open) + @patch('sonic_platform.sfp.SFP', MagicMock(return_value=MockSFPxcvrapi(False, True))) + def test_modules_mgmt_bad_flows_ports_powered_off_fw_controlled(self, mock_open): + mock_open.side_effect = self.mock_open_new_side_effect_poller_test + global TESTED + TESTED = False + num_of_ports = 32 + DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=num_of_ports) + num_of_tested_ports = DeviceDataManager.get_sfp_count() + assert num_of_tested_ports == num_of_ports + + # create or update different sysfs and is_file mocking with relevant value for each port + for i in range(num_of_tested_ports): + # mock power_on sysfs for all ports + modules_sysfs = modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format(f"{i}") + mock_file_content[modules_sysfs] = "0" + mock_is_file_indep_mode_enabled_content[modules_sysfs] = True + self.fd_number_by_fd_name_dict[modules_sysfs] = 300 + i + # mock hw_presence sysfs for all ports + modules_sysfs = modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format(f'{i}') + mock_file_content[modules_sysfs] = "1" + mock_is_file_indep_mode_enabled_content[modules_sysfs] = True + self.fd_number_by_fd_name_dict[modules_sysfs] = i + # mock power_good sysfs for all ports + modules_sysfs = modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format(f'{i}') + mock_file_content[modules_sysfs] = "1" + mock_is_file_indep_mode_enabled_content[modules_sysfs] = True + self.fd_number_by_fd_name_dict[modules_sysfs] = 200 + i + # mock hw_reset sysfs for all ports + modules_sysfs = modules_mgmt.SYSFS_INDEPENDENT_FD_HW_RESET.format(f'{i}') + mock_is_file_indep_mode_enabled_content[modules_sysfs] = True + self.fd_number_by_fd_name_dict[modules_sysfs] = 400 + i + + # start modules_mgmt thread and the test in poller part + modules_mgmt_task_stopping_event = threading.Event() + modules_changes_queue = queue.Queue() + modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=modules_mgmt_task_stopping_event + , q=modules_changes_queue) + with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(modules_mgmt_task_stopping_event + , modules_mgmt_thrd, num_of_tested_ports, fw_controlled_ports=True))): + modules_mgmt_thrd.check_power_cap = check_power_cap + modules_mgmt_thrd.run() + + # change power_on sysfs values back to the default ones + for i in range(num_of_tested_ports): + modules_sysfs = modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format(f"{i}") + mock_file_content[modules_sysfs] = "1" + # a check that modules mgmt thread ran and got into the poller part + assert TESTED + + @patch('os.path.isfile', MagicMock(side_effect=mock_is_file_indep_mode_enabled)) + @patch('builtins.open', spec=open) + @patch('sonic_platform.sfp.SFP', MagicMock(return_value=MockSFPxcvrapi())) + def test_modules_mgmt_bad_flows_ports_powered_off_sw_controlled(self, mock_open): + mock_open.side_effect = self.mock_open_new_side_effect_poller_test + global TESTED + TESTED = False + num_of_ports = 32 + DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=num_of_ports) + num_of_tested_ports = DeviceDataManager.get_sfp_count() + assert num_of_tested_ports == num_of_ports + + # create or update different sysfs and is_file mocking with relevant value for each port + for i in range(num_of_tested_ports): + # mock power_on sysfs for all ports + modules_sysfs = modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format(f"{i}") + mock_file_content[modules_sysfs] = "0" + mock_is_file_indep_mode_enabled_content[modules_sysfs] = True + self.fd_number_by_fd_name_dict[modules_sysfs] = 300 + i + # mock hw_presence sysfs for all ports + modules_sysfs = modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format(f'{i}') + mock_file_content[modules_sysfs] = "1" + mock_is_file_indep_mode_enabled_content[modules_sysfs] = True + self.fd_number_by_fd_name_dict[modules_sysfs] = i + # mock power_good sysfs for all ports + modules_sysfs = modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format(f'{i}') + mock_file_content[modules_sysfs] = "1" + mock_is_file_indep_mode_enabled_content[modules_sysfs] = True + self.fd_number_by_fd_name_dict[modules_sysfs] = 200 + i + # mock hw_reset sysfs for all ports + modules_sysfs = modules_mgmt.SYSFS_INDEPENDENT_FD_HW_RESET.format(f'{i}') + mock_is_file_indep_mode_enabled_content[modules_sysfs] = True + self.fd_number_by_fd_name_dict[modules_sysfs] = 400 + i + # mock frequency_support sysfs for all ports + modules_sysfs = modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format(f'{i}') + mock_file_content[modules_sysfs] = "0" + mock_is_file_indep_mode_enabled_content[modules_sysfs] = True + self.fd_number_by_fd_name_dict[modules_sysfs] = 600 + i + + # start modules_mgmt thread and the test in poller part + modules_mgmt_task_stopping_event = threading.Event() + modules_changes_queue = queue.Queue() + modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=modules_mgmt_task_stopping_event + , q=modules_changes_queue) + with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(modules_mgmt_task_stopping_event + , modules_mgmt_thrd, num_of_tested_ports))): + modules_mgmt_thrd.check_power_cap = check_power_cap + modules_mgmt_thrd.run() + + # change power_on sysfs values back to the default ones + for i in range(num_of_tested_ports): + modules_sysfs = modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format(f"{i}") + mock_file_content[modules_sysfs] = "1" + # a check that modules mgmt thread ran and got into the poller part + assert TESTED + + def teardown_class(cls): + mock_file_content[modules_mgmt.PROC_CMDLINE] = ''