Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Mellanox] Add more unit test coverage for platform API #182

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,18 +198,6 @@ def deinitialize_sdk_handle(sdk_handle):
return False


class SdkHandleContext(object):
def __init__(self):
self.sdk_handle = None

def __enter__(self):
self.sdk_handle = initialize_sdk_handle()
return self.sdk_handle

def __exit__(self, exc_type, exc_val, exc_tb):
deinitialize_sdk_handle(self.sdk_handle)


class NvidiaSFPCommon(SfpOptoeBase):
def __init__(self, sfp_index):
super(NvidiaSFPCommon, self).__init__()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def __init__(self, wd_device_path):
super(WatchdogImplBase, self).__init__()

self.watchdog_path = wd_device_path
self.watchdog = os.open(self.watchdog_path, os.O_WRONLY)
self.watchdog = self.open_handle()

# Opening a watchdog descriptor starts
# watchdog timer;
Expand All @@ -90,6 +90,9 @@ def __init__(self, wd_device_path):

self.timeout = self._gettimeout()

def open_handle(self):
return os.open(self.watchdog_path, os.O_WRONLY)

def _enablecard(self):
"""
Turn on the watchdog timer
Expand Down Expand Up @@ -290,6 +293,7 @@ def get_watchdog():
for device in os.listdir("/dev/"):
if device.startswith("watchdog") and is_mlnx_wd_main(device):
watchdog_main_device_name = device
break

if watchdog_main_device_name is None:
return None
Expand Down
Binary file added platform/mellanox/mlnx-platform-api/tests/dmi_file
Binary file not shown.
5 changes: 5 additions & 0 deletions platform/mellanox/mlnx-platform-api/tests/test_chassis.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,3 +326,8 @@ def test_get_port_or_cage_type(self):
exceptionRaised = True

assert exceptionRaised

def test_parse_dmi(self):
chassis = Chassis()
content = chassis._parse_dmi(os.path.join(test_path, 'dmi_file'))
assert content.get('Version') == 'A4'
502 changes: 502 additions & 0 deletions platform/mellanox/mlnx-platform-api/tests/test_component.py

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions platform/mellanox/mlnx-platform-api/tests/test_device_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import os
import pytest
import subprocess
import sys
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


class TestDeviceData:
@mock.patch('sonic_platform.device_data.utils.read_int_from_file', mock.MagicMock(return_value=1))
def test_is_fan_hotswapable(self):
assert DeviceDataManager.is_fan_hotswapable()

@mock.patch('sonic_platform.device_data.utils.read_int_from_file', mock.MagicMock(return_value=1))
def test_get_linecard_sfp_count(self):
assert DeviceDataManager.get_linecard_sfp_count(1) == 1

@mock.patch('sonic_platform.device_data.utils.read_int_from_file', mock.MagicMock(return_value=1))
def test_get_gearbox_count(self):
assert DeviceDataManager.get_gearbox_count('') == 1

@mock.patch('sonic_platform.device_data.DeviceDataManager.get_platform_name', mock.MagicMock(return_value='x86_64-mlnx_msn3420-r0'))
def test_get_linecard_max_port_count(self):
assert DeviceDataManager.get_linecard_max_port_count() == 0

@mock.patch('sonic_platform.device_data.DeviceDataManager.get_platform_name', mock.MagicMock(return_value='x86_64-nvidia_sn2201-r0'))
def test_get_bios_component(self):
assert DeviceDataManager.get_bios_component() is not None



37 changes: 37 additions & 0 deletions platform/mellanox/mlnx-platform-api/tests/test_led.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,40 @@ def test_fixed_psu_led(self):
psu = FixedPsu(0)
physical_led = psu.led
self._verify_non_shared_led(physical_led, psu)

def test_get_actual_color(self):
led = Led()
assert led._get_actual_color('red') is None
led.supported_colors.add('orange')
assert led._get_actual_color('red') is 'orange'

@mock.patch('os.path.exists')
@mock.patch('time.sleep', mock.MagicMock())
def test_wait_files_ready(self, mock_exists):
mock_exists.side_effect = [True, True]
led = Led()
assert led._wait_files_ready(['a', 'b'])
mock_exists.side_effect = [False, False, True, True]
assert led._wait_files_ready(['a', 'b'])
mock_exists.side_effect = None
mock_exists.return_value = False
assert not led._wait_files_ready(['a', 'b'])

@mock.patch('sonic_platform.utils.write_file')
@mock.patch('sonic_platform.led.Led.get_led_path', mock.MagicMock())
@mock.patch('sonic_platform.led.Led._stop_blink', mock.MagicMock())
@mock.patch('sonic_platform.led.Led.get_capability', mock.MagicMock())
@mock.patch('sonic_platform.device_data.DeviceDataManager.is_simx_platform', mock.MagicMock(return_value=False))
def test_get_set_led_status(self, mock_write):
led = Led()
led._led_id = 'fan'
led.supported_colors.add('red')
led.supported_colors.add('green')
assert not led.set_status('black')
assert led.set_status(led.STATUS_LED_COLOR_OFF)
assert mock_write.call_count == 2
mock_write.side_effect = ValueError('')
assert not led.set_status(led.STATUS_LED_COLOR_OFF)

led.supported_colors.clear()
assert led.get_status() == led.STATUS_LED_COLOR_OFF
50 changes: 50 additions & 0 deletions platform/mellanox/mlnx-platform-api/tests/test_pcie.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import os
import sys
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.pcie import Pcie


class TestPcie:
@mock.patch('sonic_platform.pcie.Pcie._create_device_id_to_bus_map', mock.MagicMock())
@mock.patch('sonic_platform.pcie.Pcie.load_config_file', mock.MagicMock())
def test_get_pcie_check(self):
p = Pcie('')
p._device_id_to_bus_map = {}
p.confInfo = [
{
'id': '1f0b',
'dev': '00',
'fn': '00'
}
]
info = p.get_pcie_check()
assert info[0]['result'] == 'Failed'

p.check_pcie_sysfs = mock.MagicMock(return_value=False)
p._device_id_to_bus_map = {'1f0b': '00'}
info = p.get_pcie_check()
assert info[0]['result'] == 'Failed'

p.check_pcie_sysfs = mock.MagicMock(return_value=True)
info = p.get_pcie_check()
assert info[0]['result'] == 'Passed'

@mock.patch('sonic_platform.pcie.os.listdir')
@mock.patch('sonic_platform.pcie.Pcie.load_config_file', mock.MagicMock())
def test_create_device_id_to_bus_map(self, mock_dir):
p = Pcie('')
assert not p._device_id_to_bus_map
mock_dir.return_value = ['0000:01:00.0']

mock_os_open = mock.mock_open(read_data='0x23')
with mock.patch('sonic_platform.pcie.open', mock_os_open):
p._create_device_id_to_bus_map()
assert p._device_id_to_bus_map == {'23':'01'}
12 changes: 12 additions & 0 deletions platform/mellanox/mlnx-platform-api/tests/test_psu.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,14 @@ def test_fixed_psu(self):
assert psu.get_model() == 'N/A'
assert psu.get_serial() == 'N/A'
assert psu.get_revision() == 'N/A'
avail, msg = psu.get_power_available_status()
assert not avail
assert msg == 'absence of power'
utils.read_int_from_file = mock.MagicMock(return_value=1)
assert psu.get_powergood_status()
avail, msg = psu.get_power_available_status()
assert avail
assert msg == ''
utils.read_int_from_file = mock.MagicMock(return_value=0)
assert not psu.get_powergood_status()
assert psu.get_presence()
Expand Down Expand Up @@ -69,6 +75,7 @@ def test_psu(self):
psu.psu_temp_threshold: 50678,
psu.psu_voltage_in: 102345,
psu.psu_current_in: 676,
psu.psu_power_max: 1234567
}

def mock_read_int_from_file(file_path, **kwargs):
Expand All @@ -77,8 +84,12 @@ def mock_read_int_from_file(file_path, **kwargs):
utils.read_int_from_file = mock_read_int_from_file
utils.read_str_from_file = mock.MagicMock(return_value='min max')
assert psu.get_presence() is True
assert psu.get_maximum_supplied_power() == 1.234567
mock_sysfs_content[psu.psu_presence] = 0
assert psu.get_presence() is False
avail, msg = psu.get_power_available_status()
assert not avail
assert msg == 'absence of PSU'

assert psu.get_powergood_status() is True
mock_sysfs_content[psu.psu_oper_status] = 0
Expand All @@ -91,6 +102,7 @@ def mock_read_int_from_file(file_path, **kwargs):
assert psu.get_temperature_high_threshold() is None
assert psu.get_input_voltage() is None
assert psu.get_input_current() is None
assert psu.get_maximum_supplied_power() is None

mock_sysfs_content[psu.psu_oper_status] = 1
assert psu.get_voltage() == 10.234
Expand Down
23 changes: 23 additions & 0 deletions platform/mellanox/mlnx-platform-api/tests/test_sfp.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class TestSfp:
@mock.patch('sonic_platform.device_data.DeviceDataManager.get_linecard_max_port_count')
def test_sfp_index(self, mock_max_port):
sfp = SFP(0)
assert sfp.is_replaceable()
assert sfp.sdk_index == 0
assert sfp.index == 1

Expand Down Expand Up @@ -267,3 +268,25 @@ def test_set_lpmode(self, mock_read_int, mock_write):

assert sfp.set_lpmode(True)
mock_write.assert_called_with('/sys/module/sx_core/asic0/module0/power_mode_policy', '2')

@mock.patch('sonic_platform.sfp.SFP.read_eeprom')
def test_get_xcvr_api(self, mock_read):
sfp = SFP(0)
api = sfp.get_xcvr_api()
assert api is None
mock_read.return_value = bytearray([0x18])
api = sfp.get_xcvr_api()
assert api is not None

def test_rj45_basic(self):
sfp = RJ45Port(0)
assert not sfp.get_lpmode()
assert not sfp.reset()
assert not sfp.set_lpmode(True)
assert not sfp.get_error_description()
assert not sfp.get_reset_status()
assert sfp.read_eeprom(0, 0) is None
assert sfp.get_transceiver_info()
assert sfp.get_transceiver_bulk_status()
assert sfp.get_transceiver_threshold_info()
sfp.reinit()
52 changes: 25 additions & 27 deletions platform/mellanox/mlnx-platform-api/tests/test_thermal.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ class TestThermal:
@mock.patch('sonic_platform.device_data.DeviceDataManager.get_platform_name', mock.MagicMock(return_value='x86_64-mlnx_msn2700-r0'))
def test_chassis_thermal(self):
from sonic_platform.thermal import THERMAL_NAMING_RULE
os.path.exists = mock.MagicMock(return_value=True)
chassis = Chassis()
thermal_list = chassis.get_all_thermals()
assert thermal_list
Expand Down Expand Up @@ -123,9 +122,9 @@ def test_chassis_thermal_includes(self, mock_capability):
thermal_name = rule['name']
assert thermal_name in thermal_dict

@mock.patch('os.path.exists', mock.MagicMock(return_value=True))
def test_psu_thermal(self):
from sonic_platform.thermal import initialize_psu_thermal, THERMAL_NAMING_RULE
os.path.exists = mock.MagicMock(return_value=True)
presence_cb = mock.MagicMock(return_value=(True, ''))
thermal_list = initialize_psu_thermal(0, presence_cb)
assert len(thermal_list) == 1
Expand All @@ -147,9 +146,9 @@ def test_psu_thermal(self):
assert thermal.get_high_threshold() is None
assert thermal.get_high_critical_threshold() is None

@mock.patch('os.path.exists', mock.MagicMock(return_value=True))
def test_sfp_thermal(self):
from sonic_platform.thermal import initialize_sfp_thermal, THERMAL_NAMING_RULE
os.path.exists = mock.MagicMock(return_value=True)
thermal_list = initialize_sfp_thermal(0)
assert len(thermal_list) == 1
thermal = thermal_list[0]
Expand All @@ -162,66 +161,65 @@ def test_sfp_thermal(self):
assert thermal.get_position_in_parent() == 1
assert thermal.is_replaceable() == False

def test_get_temperature(self):
@mock.patch('sonic_platform.utils.read_float_from_file')
def test_get_temperature(self, mock_read):
from sonic_platform.thermal import Thermal
from sonic_platform import utils
thermal = Thermal('test', 'temp_file', None, None, 1)
utils.read_float_from_file = mock.MagicMock(return_value=35727)
mock_read.return_value = 35727
assert thermal.get_temperature() == 35.727

utils.read_float_from_file = mock.MagicMock(return_value=0.0)
mock_read.return_value = 0.0
assert thermal.get_temperature() is None

utils.read_float_from_file = mock.MagicMock(return_value=None)
mock_read.return_value = None
assert thermal.get_temperature() is None

def test_get_high_threshold(self):
@mock.patch('sonic_platform.utils.read_float_from_file')
def test_get_high_threshold(self, mock_read):
from sonic_platform.thermal import Thermal
from sonic_platform import utils
thermal = Thermal('test', None, None, None, 1)
assert thermal.get_high_threshold() is None

thermal.high_threshold = 'high_th_file'
utils.read_float_from_file = mock.MagicMock(return_value=25833)
mock_read.return_value = 25833
assert thermal.get_temperature() == 25.833

utils.read_float_from_file = mock.MagicMock(return_value=0.0)
mock_read.return_value = 0.0
assert thermal.get_temperature() is None

utils.read_float_from_file = mock.MagicMock(return_value=None)
mock_read.return_value = None
assert thermal.get_temperature() is None

def test_get_high_critical_threshold(self):
@mock.patch('sonic_platform.utils.read_float_from_file')
def test_get_high_critical_threshold(self, mock_read):
from sonic_platform.thermal import Thermal
from sonic_platform import utils
thermal = Thermal('test', None, None, None, 1)
assert thermal.get_high_critical_threshold() is None

thermal.high_critical_threshold = 'high_th_file'
utils.read_float_from_file = mock.MagicMock(return_value=120839)
mock_read.return_value = 120839
assert thermal.get_high_critical_threshold() == 120.839

utils.read_float_from_file = mock.MagicMock(return_value=0.0)
mock_read.return_value = 0.0
assert thermal.get_high_critical_threshold() is None

utils.read_float_from_file = mock.MagicMock(return_value=None)
mock_read.return_value = None
assert thermal.get_high_critical_threshold() is None

def test_set_thermal_algorithm_status(self):
@mock.patch('glob.iglob', mock.MagicMock(return_value=['thermal_zone1', 'thermal_zone2']))
@mock.patch('sonic_platform.utils.write_file')
def test_set_thermal_algorithm_status(self, mock_write):
from sonic_platform.thermal import Thermal, THERMAL_ZONE_FOLDER_WILDCARD, THERMAL_ZONE_POLICY_FILE, THERMAL_ZONE_MODE_FILE
from sonic_platform import utils
glob.iglob = mock.MagicMock(return_value=['thermal_zone1', 'thermal_zone2'])
utils.write_file = mock.MagicMock()
assert Thermal.set_thermal_algorithm_status(True, False)

for folder in glob.iglob(THERMAL_ZONE_FOLDER_WILDCARD):
utils.write_file.assert_any_call(os.path.join(folder, THERMAL_ZONE_POLICY_FILE), 'step_wise')
utils.write_file.assert_any_call(os.path.join(folder, THERMAL_ZONE_MODE_FILE), 'enabled')
mock_write.assert_any_call(os.path.join(folder, THERMAL_ZONE_POLICY_FILE), 'step_wise')
mock_write.assert_any_call(os.path.join(folder, THERMAL_ZONE_MODE_FILE), 'enabled')

assert Thermal.set_thermal_algorithm_status(False, False)
for folder in glob.iglob(THERMAL_ZONE_FOLDER_WILDCARD):
utils.write_file.assert_any_call(os.path.join(folder, THERMAL_ZONE_POLICY_FILE), 'user_space')
utils.write_file.assert_any_call(os.path.join(folder, THERMAL_ZONE_MODE_FILE), 'disabled')
mock_write.assert_any_call(os.path.join(folder, THERMAL_ZONE_POLICY_FILE), 'user_space')
mock_write.assert_any_call(os.path.join(folder, THERMAL_ZONE_MODE_FILE), 'disabled')

assert not Thermal.set_thermal_algorithm_status(False, False)

Expand Down Expand Up @@ -283,10 +281,10 @@ def mock_read_int_from_file(file_path, **kwargs):
mock_file_content[os.path.join('thermal_zone2', THERMAL_ZONE_TEMP_FILE)] = 81000
assert Thermal.get_min_allowed_cooling_level_by_thermal_zone() is None

@mock.patch('glob.iglob', mock.MagicMock(return_value=['thermal_zone1', 'thermal_zone2']))
def test_check_module_temperature_trustable(self):
from sonic_platform.thermal import Thermal
from sonic_platform import utils
glob.iglob = mock.MagicMock(return_value=['thermal_zone1', 'thermal_zone2'])

utils.read_int_from_file = mock.MagicMock(return_value=1)
assert Thermal.check_module_temperature_trustable() == 'untrust'
Expand Down
Loading