Skip to content
Merged
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
10 changes: 8 additions & 2 deletions fwutil/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,9 @@ def get_platform(self):
def get_chassis(self):
return self.__chassis

def is_smart_switch(self):
return self.__chassis.is_smartswitch()

def is_modular_chassis(self):
return len(self.module_component_map) > 0

Expand Down Expand Up @@ -535,8 +538,8 @@ def __init__(self, root_path=None):
os.mkdir(FIRMWARE_AU_STATUS_DIR)

self.__root_path = root_path

self.__pcp = PlatformComponentsParser(self.is_modular_chassis())
is_modular_chassis = self.is_modular_chassis() and not self.is_smart_switch()
self.__pcp = PlatformComponentsParser(is_modular_chassis)
self.__pcp.parse_platform_components(root_path)

self.__validate_platform_schema(self.__pcp)
Expand All @@ -547,6 +550,9 @@ def __diff_keys(self, keys1, keys2):
def __validate_component_map(self, section, pdp_map, pcp_map):
diff_keys = self.__diff_keys(list(pdp_map.keys()), list(pcp_map.keys()))

if diff_keys and section == self.SECTION_MODULE and self.is_smart_switch():
return

if diff_keys:
raise RuntimeError(
"{} names mismatch: keys={}".format(
Expand Down
149 changes: 149 additions & 0 deletions tests/fwutil_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,154 @@ def test_is_capable_auto_update(self):
assert CUProvider.is_capable_auto_update('none') == True
assert CUProvider.is_capable_auto_update('def') == True

@patch('fwutil.lib.Platform')
@patch('fwutil.lib.PlatformComponentsParser')
@patch('fwutil.lib.ComponentUpdateProvider._ComponentUpdateProvider__validate_platform_schema')
@patch('os.path.isdir', return_value=True)
def test_is_smart_switch_method(self, mock_isdir, mock_validate,
mock_parser_class, mock_platform_class):
"""Test that the is_smart_switch method correctly returns True
when the chassis.is_smartswitch() method returns True."""
# Setup mock chassis
mock_chassis = MagicMock()
mock_chassis.is_smartswitch.return_value = True

# Setup mock platform
mock_platform = MagicMock()
mock_platform.get_chassis.return_value = mock_chassis
mock_platform_class.return_value = mock_platform

# Create ComponentUpdateProvider instance
cup = fwutil_lib.ComponentUpdateProvider()

# Test is_smart_switch method
assert cup.is_smart_switch()
mock_chassis.is_smartswitch.assert_called_once()

@patch('fwutil.lib.Platform')
@patch('fwutil.lib.PlatformComponentsParser')
@patch('fwutil.lib.ComponentUpdateProvider._ComponentUpdateProvider__validate_platform_schema')
@patch('os.mkdir')
def test_smartswitch_modular_chassis_parsing(self, mock_mkdir, mock_validate,
mock_parser_class, mock_platform_class):
"""Test that SmartSwitch devices with modules are passed as non-modular (False)
to the PlatformComponentsParser constructor."""
# Setup mock chassis that is SmartSwitch and has modules
mock_chassis = MagicMock()
mock_chassis.is_smartswitch.return_value = True
mock_chassis.get_all_modules.return_value = [MagicMock(), MagicMock()] # 2 modules

# Setup mock platform
mock_platform = MagicMock()
mock_platform.get_chassis.return_value = mock_chassis
mock_platform_class.return_value = mock_platform

# Setup mock parser
mock_parser = MagicMock()
mock_parser_class.return_value = mock_parser

# Create ComponentUpdateProvider instance
fwutil_lib.ComponentUpdateProvider()

# Verify that PlatformComponentsParser was called with is_modular_chassis=False
# because SmartSwitch should be treated as non-modular for parsing purposes
mock_parser_class.assert_called_once_with(False)

@patch('fwutil.lib.Platform')
@patch('fwutil.lib.PlatformComponentsParser')
@patch('fwutil.lib.ComponentUpdateProvider._ComponentUpdateProvider__validate_platform_schema')
@patch('os.mkdir')
def test_regular_modular_chassis_parsing(self, mock_mkdir, mock_validate, mock_parser_class, mock_platform_class):
"""Test that regular modular chassis is treated as modular for parsing"""
# Setup mock chassis that is not SmartSwitch but has modules
mock_chassis = MagicMock()
mock_chassis.is_smartswitch.return_value = False
mock_chassis.get_all_modules.return_value = [MagicMock(), MagicMock()] # 2 modules

# Setup mock platform
mock_platform = MagicMock()
mock_platform.get_chassis.return_value = mock_chassis
mock_platform_class.return_value = mock_platform

# Setup mock parser
mock_parser = MagicMock()
mock_parser_class.return_value = mock_parser

# Create ComponentUpdateProvider instance
fwutil_lib.ComponentUpdateProvider()

# Verify that PlatformComponentsParser was called with is_modular_chassis=True
# because regular modular chassis should be treated as modular
mock_parser_class.assert_called_once_with(True)

@patch('fwutil.lib.Platform')
@patch('fwutil.lib.PlatformComponentsParser')
@patch('fwutil.lib.ComponentUpdateProvider._ComponentUpdateProvider__validate_platform_schema')
@patch('os.mkdir')
def test_smartswitch_module_validation_skip(self, mock_mkdir, mock_validate,
mock_parser_class, mock_platform_class):
"""Test that module validation is skipped for SmartSwitch platforms"""
# Setup mock chassis that is SmartSwitch
mock_chassis = MagicMock()
mock_chassis.is_smartswitch.return_value = True
mock_chassis.get_all_modules.return_value = [MagicMock()] # Has modules

# Setup mock platform
mock_platform = MagicMock()
mock_platform.get_chassis.return_value = mock_chassis
mock_platform_class.return_value = mock_platform

# Setup mock parser
mock_parser = MagicMock()
mock_parser_class.return_value = mock_parser

# Create ComponentUpdateProvider instance
cup = fwutil_lib.ComponentUpdateProvider()

# Test that module validation is skipped for SmartSwitch
# This should not raise an exception even if there are differences
pdp_map = {'module1': {'comp1': MagicMock()}}
pcp_map = {'module2': {'comp2': MagicMock()}} # Different modules

# Should not raise exception for SmartSwitch module validation
cup._ComponentUpdateProvider__validate_component_map(
cup.SECTION_MODULE, pdp_map, pcp_map
)

@patch('fwutil.lib.Platform')
@patch('fwutil.lib.PlatformComponentsParser')
@patch('fwutil.lib.ComponentUpdateProvider._ComponentUpdateProvider__validate_platform_schema')
@patch('os.mkdir')
def test_regular_chassis_module_validation_error(self, mock_mkdir, mock_validate,
mock_parser_class, mock_platform_class):
"""Test that module validation raises error for regular modular chassis"""
# Setup mock chassis that is not SmartSwitch but has modules
mock_chassis = MagicMock()
mock_chassis.is_smartswitch.return_value = False
mock_chassis.get_all_modules.return_value = [MagicMock()] # Has modules

# Setup mock platform
mock_platform = MagicMock()
mock_platform.get_chassis.return_value = mock_chassis
mock_platform_class.return_value = mock_platform

# Setup mock parser
mock_parser = MagicMock()
mock_parser_class.return_value = mock_parser

# Create ComponentUpdateProvider instance
cup = fwutil_lib.ComponentUpdateProvider()

# Test that module validation raises error for regular modular chassis
pdp_map = {'module1': {'comp1': MagicMock()}}
pcp_map = {'module2': {'comp2': MagicMock()}} # Different modules

# Should raise exception for regular modular chassis
with pytest.raises(RuntimeError) as excinfo:
cup._ComponentUpdateProvider__validate_component_map(
cup.SECTION_MODULE, pdp_map, pcp_map
)
assert "Module names mismatch" in str(excinfo.value)

def teardown(self):
print('TEARDOWN')
Loading