ac35a0fafb
* add unit tests for CMIS host management feature
801 lines
43 KiB
Python
801 lines
43 KiB
Python
#
|
|
# Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES.
|
|
# Apache-2.0
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
#
|
|
|
|
import os
|
|
import queue
|
|
import sys
|
|
import threading
|
|
import time
|
|
import types
|
|
import unittest
|
|
|
|
from mock import MagicMock, patch, mock_open, Mock
|
|
if sys.version_info.major == 3:
|
|
from unittest import mock
|
|
else:
|
|
import mock
|
|
|
|
test_path = os.path.dirname(os.path.abspath(__file__))
|
|
modules_path = os.path.dirname(test_path)
|
|
sys.path.insert(0, modules_path)
|
|
|
|
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_platform_base.sonic_xcvr.api.public.cmis import CmisApi
|
|
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
|
|
|
|
DEFAULT_NUM_OF_PORTS_1 = 1
|
|
DEFAULT_NUM_OF_PORTS_3 = 3
|
|
DEFAULT_NUM_OF_PORTS_32 = 32
|
|
POLLER_EXECUTED = False
|
|
|
|
def _mock_sysfs_default_file_content():
|
|
return {
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("0"): "1",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("1"): "1",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("2"): "1",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("0"): "1",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("1"): "1",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("2"): "1",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("0"): "1",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("1"): "1",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("2"): "1",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("0"): "48",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("1"): "48",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("2"): "48",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("0"): "0",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("1"): "0",
|
|
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_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: ""
|
|
}
|
|
|
|
|
|
mock_file_content = _mock_sysfs_default_file_content()
|
|
|
|
|
|
class MockPoller:
|
|
|
|
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, sleep_timeout=False):
|
|
self.fds_dict = {}
|
|
self.poller_iteration_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.port_plug_out_changed = False
|
|
self.port_plug_in_changed = False
|
|
self.sleep_timeout = sleep_timeout
|
|
|
|
def register(self, fd, attrs):
|
|
self.fds_dict[fd.fileno()] = { fd : attrs }
|
|
assert fd.fileno() in self.fds_dict
|
|
|
|
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 POLLER_EXECUTED
|
|
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
|
|
# counting the number of poller iterations to know when to do the checks after plug out (and plug in)
|
|
# have to check at least on iteration 7 to let ports reach final state
|
|
self.poller_iteration_count += 1
|
|
if self.num_of_ports > 0:
|
|
if not self.port_plug_out_changed:
|
|
if self.port_plug_out:
|
|
# return first fd registered with some made up event number 870
|
|
fd_no_to_return = list(self.fds_dict.keys())[0]
|
|
fd = list(self.fds_dict[fd_no_to_return].keys())[0]
|
|
fd.set_file_int_content(0)
|
|
event_to_return = 870
|
|
self.port_plug_out_changed = True
|
|
return [(fd_no_to_return, event_to_return)]
|
|
if not self.port_plug_in_changed:
|
|
if self.port_plug_in:
|
|
# return first fd registered with some made up event number 871
|
|
fd_no_to_return = list(self.fds_dict.keys())[0]
|
|
fd = list(self.fds_dict[fd_no_to_return].keys())[0]
|
|
fd.set_file_int_content(1)
|
|
event_to_return = 871
|
|
self.port_plug_in_changed = True
|
|
return [(fd_no_to_return, event_to_return)]
|
|
if 7 == self.poller_iteration_count:
|
|
# when feature is enabled, need to check for each port both power_good and hw_present sysfs for
|
|
# cmis non-flat memory cables
|
|
num_of_sysfs_to_check = 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(num_of_sysfs_to_check):
|
|
# when feature is enabled, power_good sysfs is also registered for cmis non-flat memory cables
|
|
# so each SW controlled port has 2 fds registered
|
|
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:
|
|
# in tests other than warm reboot it creates only SW control ports
|
|
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
|
|
# in warm reboot test with plug out plug in test creates only FW control ports
|
|
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
|
|
POLLER_EXECUTED = True
|
|
self.modules_mgmt_task_stopping_event.set()
|
|
if self.sleep_timeout:
|
|
time.sleep(timeout/1000)
|
|
return []
|
|
|
|
|
|
class MockOpen:
|
|
|
|
def __init__(self, name='', file_no=None, indep_mode_supported=True):
|
|
self.name = name
|
|
self.file_no = file_no
|
|
self.indep_mode_supported = indep_mode_supported
|
|
self.retint = None
|
|
self.curr = 0
|
|
|
|
def read(self):
|
|
if self.fileno() in [SAI_PROFILE_FD_FILENO]:
|
|
pass
|
|
else:
|
|
# if return value was changed, i.e. sysfs content changed from 1 to 0 to simulate plug out
|
|
if self.retint is not None:
|
|
return str(self.retint)
|
|
# return default values (can be changed per test)
|
|
else:
|
|
return mock_file_content[self.name]
|
|
|
|
def readline(self):
|
|
# if trying to read sai profile file, according to fd fileno
|
|
if self.fileno() in [SAI_PROFILE_FD_FILENO]:
|
|
if self.indep_mode_supported:
|
|
return "SAI_INDEPENDENT_MODULE_MODE=1"
|
|
else:
|
|
return ""
|
|
else:
|
|
return mock_file_content[self.name]
|
|
|
|
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):
|
|
self.retint = str(retint)
|
|
mock_file_content[self.name] = str(retint)
|
|
|
|
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, num_of_ports=DEFAULT_NUM_OF_PORTS_3
|
|
, feature_enabled=True, ports_connected=True, fw_controlled_ports=False, sleep_timeout=False):
|
|
self.fds_dict = {}
|
|
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.ports_connected = ports_connected
|
|
self.sleep_timeout = sleep_timeout
|
|
self.fw_controlled_ports = fw_controlled_ports
|
|
|
|
def register(self, fd, attrs):
|
|
self.fds_dict[fd.fileno()] = 1 & attrs
|
|
assert fd.fileno() in self.fds_dict
|
|
|
|
def poll(self, timeout=0):
|
|
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
|
|
global POLLER_EXECUTED
|
|
if self.num_of_ports > 0:
|
|
# when feature is enabled, need to check for each port both power_good and hw_present sysfs for
|
|
# cmis non-flat memory cables
|
|
ports_to_test = self.num_of_ports if (not self.feature_enabled or not self.ports_connected
|
|
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 or not self.ports_connected
|
|
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
|
|
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_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_NOT_PRESENT
|
|
POLLER_EXECUTED = True
|
|
else:
|
|
POLLER_EXECUTED = True
|
|
self.modules_mgmt_task_stopping_event.set()
|
|
if self.sleep_timeout:
|
|
time.sleep(timeout/1000)
|
|
return []
|
|
|
|
|
|
def _mock_is_file_indep_mode_disabled_content():
|
|
return {
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE: True,
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD: True,
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON: True,
|
|
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_LEGACY_FD_PRESENCE.format("1"): True,
|
|
modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2"): True,
|
|
'//usr/share/sonic/platform/ACS-MSN4700/sai.profile' : True
|
|
}
|
|
|
|
mock_is_file_indep_mode_disabled_content = _mock_is_file_indep_mode_disabled_content()
|
|
|
|
def mock_is_file_indep_mode_disabled(file_path, **kwargs):
|
|
return mock_is_file_indep_mode_disabled_content[file_path]
|
|
|
|
def _mock_is_file_indep_mode_enabled_content():
|
|
return {
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE: True,
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD: True,
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON: True,
|
|
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,
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("0"): True,
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("1"): True,
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("2"): True,
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("0"): True,
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("1"): True,
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("2"): True,
|
|
'//usr/share/sonic/platform/ACS-MSN4700/sai.profile' : True
|
|
}
|
|
|
|
mock_is_file_indep_mode_enabled_content = _mock_is_file_indep_mode_enabled_content()
|
|
|
|
|
|
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(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]
|
|
|
|
|
|
class MockXcvrEeprom():
|
|
def __init__(self, is_flat_memory, mem_map):
|
|
self.is_flat_memory = is_flat_memory
|
|
self.mem_map = mem_map
|
|
|
|
def is_cmis_api(self):
|
|
return self.is_cmis_api
|
|
|
|
def is_flat_memory(self):
|
|
return self.is_flat_memory
|
|
|
|
def read(self, field):
|
|
if consts.FLAT_MEM_FIELD == field:
|
|
return 0 if self.is_flat_memory else 1
|
|
else:
|
|
return 0
|
|
|
|
|
|
class MockXcvrapi:
|
|
def __init__(self, is_cmis_api=True, is_flat_memory_bool=False):
|
|
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(is_flat_memory_bool, CmisMemMap(CmisCodes)))
|
|
|
|
def is_flat_memory(self):
|
|
return self.is_flat_memory_bool
|
|
|
|
def xcvr_eeprom(self):
|
|
return self.xcvr_eeprom
|
|
|
|
|
|
class MockSFPxcvrapi:
|
|
def __init__(self, xcvr_api_is_cmis_api=True, xcvr_eeprom_is_flat_memory=False):
|
|
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)
|
|
|
|
def get_xcvr_api(self):
|
|
return self.xcvr_api
|
|
|
|
def is_flat_memory(self, ref):
|
|
return self.xcvr_eeprom_is_flat_memory
|
|
|
|
|
|
def check_power_cap(port, module_sm_obj):
|
|
pass
|
|
|
|
SAI_PROFILE_FD_FILENO = 99
|
|
|
|
|
|
class TestModulesMgmt(unittest.TestCase):
|
|
"""Test class to test modules_mgmt.py. The test cases covers:
|
|
1. cables detection for 1 to 3 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
|
|
"""
|
|
|
|
def _mock_sysfs_file_content(self):
|
|
return {
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE : "1",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD : "1",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON : "0",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_HW_RESET : "",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT : "48",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_FW_CONTROL : "1",
|
|
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",
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("0"): "0"
|
|
}
|
|
|
|
def mock_open_builtin(self, file_name, feature_enabled=True):
|
|
return_dict = {
|
|
(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"), 'r') : MockOpen(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"), 100),
|
|
(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1"), 'r') : MockOpen(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1"), 101),
|
|
(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2"), 'r') : MockOpen(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2"), 102),
|
|
'//usr/share/sonic/platform/ACS-MSN4700/sai.profile' : MockOpen('//usr/share/sonic/platform/ACS-MSN4700/sai.profile'
|
|
, SAI_PROFILE_FD_FILENO, feature_enabled),
|
|
modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0") : MockOpen(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("0"), 100),
|
|
modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1") : MockOpen(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("1"), 101),
|
|
modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2") : MockOpen(modules_mgmt.SYSFS_LEGACY_FD_PRESENCE.format("2"), 102),
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("0"): MockOpen(modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("0"), 0),
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("1"): MockOpen(modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("1"), 1),
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("2"): MockOpen(modules_mgmt.SYSFS_INDEPENDENT_FD_PRESENCE.format("2"), 2),
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("0"): MockOpen(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("0"), 200),
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("1"): MockOpen(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("1"), 201),
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("2"): MockOpen(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_GOOD.format("2"), 202),
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("0"): MockOpen(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("0"), 300),
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("1"): MockOpen(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("1"), 301),
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("2"): MockOpen(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_ON.format("2"), 302),
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("0"): MockOpen(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("0"), 500),
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("1"): MockOpen(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("1"), 501),
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("2"): MockOpen(modules_mgmt.SYSFS_INDEPENDENT_FD_POWER_LIMIT.format("2"), 502),
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("0"): MockOpen(modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("0"), 602),
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("1"): MockOpen(modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("1"), 602),
|
|
modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("2"): MockOpen(modules_mgmt.SYSFS_INDEPENDENT_FD_FREQ_SUPPORT.format("2"), 602),
|
|
modules_mgmt.PROC_CMDLINE: MockOpen(modules_mgmt.PROC_CMDLINE, self.fd_number_by_fd_name_dict[modules_mgmt.PROC_CMDLINE])
|
|
}
|
|
return return_dict[file_name]
|
|
|
|
# side effects are used in mock when want to create different mocks per variable, i.e. here it's filename
|
|
# see below mock_open_new_side_effect_poller_test where returning a new MockOpen passing it the filename
|
|
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, False)
|
|
mock_context.__exit__.return_value = False
|
|
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)
|
|
mock_context.__exit__.return_value = False
|
|
return mock_context
|
|
|
|
def mock_open_new_side_effect_poller_test(self, filename, *args, **kwargs):
|
|
if filename in ['//usr/share/sonic/platform/ACS-MSN4700/sai.profile']:
|
|
mock_context = MagicMock()
|
|
mock_context.__enter__.return_value = MockOpen(filename, SAI_PROFILE_FD_FILENO)
|
|
mock_context.__exit__.return_value = False
|
|
return mock_context
|
|
else:
|
|
mock_context = MagicMock()
|
|
mock_open_new = MockOpen(filename, self.fd_number_by_fd_name_dict[filename])
|
|
mock_context.return_value = mock_open_new
|
|
mock_context.__enter__.return_value = mock_open_new
|
|
mock_context.__exit__.return_value = False
|
|
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 = MockOpen(filename, SAI_PROFILE_FD_FILENO)
|
|
mock_context.__exit__.return_value = False
|
|
return mock_context
|
|
else:
|
|
mock_open_new = MockOpen(filename, self.fd_number_by_fd_name_dict[filename])
|
|
return mock_open_new
|
|
|
|
def setUp(cls):
|
|
cls.modules_mgmt_task_stopping_event = threading.Event()
|
|
cls.modules_changes_queue = queue.Queue()
|
|
global POLLER_EXECUTED
|
|
POLLER_EXECUTED = False
|
|
# start modules_mgmt thread and the test in poller part
|
|
cls.modules_mgmt_thrd = ModulesMgmtTask(main_thread_stop_event=cls.modules_mgmt_task_stopping_event,
|
|
q=cls.modules_changes_queue)
|
|
cls.modules_mgmt_thrd.check_power_cap = check_power_cap
|
|
assert cls.modules_mgmt_thrd.sfp_port_dict_initial == {}
|
|
|
|
@classmethod
|
|
def setup_class(cls):
|
|
os.environ["MLNX_PLATFORM_API_UNIT_TESTING"] = "1"
|
|
cls.fd_number_by_fd_name_dict = {
|
|
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' : SAI_PROFILE_FD_FILENO,
|
|
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") : 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 : 800
|
|
}
|
|
# 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'))
|
|
|
|
|
|
@patch('sonic_platform.device_data.DeviceDataManager.get_sfp_count', MagicMock(return_value=DEFAULT_NUM_OF_PORTS_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))
|
|
@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
|
|
num_of_tested_ports = DeviceDataManager.get_sfp_count()
|
|
assert num_of_tested_ports == DEFAULT_NUM_OF_PORTS_3
|
|
|
|
# start modules_mgmt thread and the test in poller part
|
|
with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(self.modules_mgmt_task_stopping_event
|
|
, self.modules_mgmt_thrd, feature_enabled=False))):
|
|
self.modules_mgmt_thrd.run()
|
|
|
|
@patch('sonic_platform.device_data.DeviceDataManager.get_sfp_count', MagicMock(return_value=DEFAULT_NUM_OF_PORTS_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()))
|
|
def test_mdf_all_ports_feature_enabled(self, mock_open):
|
|
mock_open.side_effect = self.mock_open_new_side_effect_feature_enabled
|
|
num_of_tested_ports = DeviceDataManager.get_sfp_count()
|
|
assert num_of_tested_ports == DEFAULT_NUM_OF_PORTS_3
|
|
|
|
# start modules_mgmt thread and the test in poller part
|
|
with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(self.modules_mgmt_task_stopping_event
|
|
, self.modules_mgmt_thrd))):
|
|
self.modules_mgmt_thrd.run()
|
|
|
|
@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_3_ports(self, mock_open):
|
|
mock_open.side_effect = self.mock_open_new_side_effect_poller_test
|
|
DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=DEFAULT_NUM_OF_PORTS_3)
|
|
num_of_tested_ports = DeviceDataManager.get_sfp_count()
|
|
assert num_of_tested_ports == DEFAULT_NUM_OF_PORTS_3
|
|
|
|
# start modules_mgmt thread and the test in poller part
|
|
with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(self.modules_mgmt_task_stopping_event
|
|
, self.modules_mgmt_thrd))):
|
|
self.modules_mgmt_thrd.run()
|
|
|
|
@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
|
|
DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=DEFAULT_NUM_OF_PORTS_1)
|
|
num_of_tested_ports = DeviceDataManager.get_sfp_count()
|
|
assert num_of_tested_ports == DEFAULT_NUM_OF_PORTS_1
|
|
|
|
# start modules_mgmt thread and the test in poller part
|
|
with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(self.modules_mgmt_task_stopping_event
|
|
, self.modules_mgmt_thrd, num_of_tested_ports))):
|
|
#with patch('builtins.open', MagicMock(side_effect=self.mock_open_new_side_effect_poller_test)):
|
|
self.modules_mgmt_thrd.run()
|
|
|
|
@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}'
|
|
DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=DEFAULT_NUM_OF_PORTS_1)
|
|
num_of_tested_ports = DeviceDataManager.get_sfp_count()
|
|
assert num_of_tested_ports == DEFAULT_NUM_OF_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
|
|
with patch('select.poll', MagicMock(return_value=MockPoller(self.modules_mgmt_task_stopping_event
|
|
, self.modules_mgmt_thrd, num_of_tested_ports, warm_reboot=True))):
|
|
self.modules_mgmt_thrd.run()
|
|
|
|
@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}'
|
|
DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=DEFAULT_NUM_OF_PORTS_1)
|
|
num_of_tested_ports = DeviceDataManager.get_sfp_count()
|
|
assert num_of_tested_ports == DEFAULT_NUM_OF_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
|
|
with patch('select.poll', MagicMock(return_value=MockPoller(self.modules_mgmt_task_stopping_event
|
|
, self.modules_mgmt_thrd, num_of_tested_ports, port_plug_out=True, warm_reboot=True))):
|
|
self.modules_mgmt_thrd.run()
|
|
|
|
@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_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}'
|
|
DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=DEFAULT_NUM_OF_PORTS_1)
|
|
num_of_tested_ports = DeviceDataManager.get_sfp_count()
|
|
assert num_of_tested_ports == DEFAULT_NUM_OF_PORTS_1
|
|
|
|
mock_file_content[modules_mgmt.SYSFS_INDEPENDENT_FD_FW_CONTROL.format("0")] = "0"
|
|
|
|
# start modules_mgmt thread and the test in poller part
|
|
with patch('select.poll', MagicMock(return_value=MockPoller(self.modules_mgmt_task_stopping_event
|
|
, self.modules_mgmt_thrd, num_of_tested_ports, port_plug_out=True, warm_reboot=True, port_plug_in=True))):
|
|
self.modules_mgmt_thrd.run()
|
|
|
|
@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
|
|
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
|
|
with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(self.modules_mgmt_task_stopping_event
|
|
, self.modules_mgmt_thrd, num_of_tested_ports))):
|
|
self.modules_mgmt_thrd.run()
|
|
|
|
@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
|
|
DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=DEFAULT_NUM_OF_PORTS_3)
|
|
num_of_tested_ports = DeviceDataManager.get_sfp_count()
|
|
assert num_of_tested_ports == DEFAULT_NUM_OF_PORTS_3
|
|
|
|
# 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
|
|
with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(self.modules_mgmt_task_stopping_event
|
|
, self.modules_mgmt_thrd, num_of_tested_ports, ports_connected=False))):
|
|
self.modules_mgmt_thrd.run()
|
|
|
|
@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
|
|
DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=DEFAULT_NUM_OF_PORTS_1)
|
|
num_of_tested_ports = DeviceDataManager.get_sfp_count()
|
|
assert num_of_tested_ports == DEFAULT_NUM_OF_PORTS_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
|
|
with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(self.modules_mgmt_task_stopping_event
|
|
, self.modules_mgmt_thrd, num_of_tested_ports, ports_connected=False))):
|
|
self.modules_mgmt_thrd.run()
|
|
|
|
@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
|
|
DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=DEFAULT_NUM_OF_PORTS_1)
|
|
num_of_tested_ports = DeviceDataManager.get_sfp_count()
|
|
assert num_of_tested_ports == DEFAULT_NUM_OF_PORTS_1
|
|
|
|
# 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
|
|
with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(self.modules_mgmt_task_stopping_event
|
|
, self.modules_mgmt_thrd, num_of_tested_ports, ports_connected=False))):
|
|
self.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"
|
|
|
|
@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
|
|
DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=DEFAULT_NUM_OF_PORTS_32)
|
|
num_of_tested_ports = DeviceDataManager.get_sfp_count()
|
|
assert num_of_tested_ports == DEFAULT_NUM_OF_PORTS_32
|
|
|
|
# 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
|
|
with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(self.modules_mgmt_task_stopping_event
|
|
, self.modules_mgmt_thrd, num_of_tested_ports, fw_controlled_ports=True))):
|
|
self.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"
|
|
|
|
@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
|
|
DeviceDataManager.get_sfp_count = mock.MagicMock(return_value=DEFAULT_NUM_OF_PORTS_32)
|
|
num_of_tested_ports = DeviceDataManager.get_sfp_count()
|
|
assert num_of_tested_ports == DEFAULT_NUM_OF_PORTS_32
|
|
|
|
# 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
|
|
with patch('select.poll', MagicMock(return_value=MockPollerStopEvent(self.modules_mgmt_task_stopping_event
|
|
, self.modules_mgmt_thrd, num_of_tested_ports))):
|
|
self.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"
|
|
|
|
def tearDown(cls):
|
|
mock_file_content[modules_mgmt.PROC_CMDLINE] = ''
|
|
cls.modules_mgmt_thrd = None
|
|
# a check that modules mgmt thread ran and got into the poller part where the tests here has all checks
|
|
assert POLLER_EXECUTED
|