@@ -468,26 +468,65 @@ def test_is_npu_si_settings_update_required(self):
468468 @patch ('xcvrd.xcvrd_utilities.port_event_helper.PortMapping.logical_port_name_to_physical_port_list' , MagicMock (return_value = [0 ]))
469469 @patch ('xcvrd.xcvrd._wrapper_get_transceiver_firmware_info' , MagicMock (return_value = {'active_firmware' : '2.1.1' ,
470470 'inactive_firmware' : '1.2.4' }))
471- @patch ('xcvrd.xcvrd._wrapper_is_flat_memory' )
471+ @patch ('xcvrd.xcvrd._wrapper_is_flat_memory' , MagicMock ( return_value = False ) )
472472 @patch ('xcvrd.xcvrd._wrapper_get_presence' )
473- def test_post_port_sfp_firmware_info_to_db (self , mock_get_presence , mock_is_flat_memory ):
473+ def test_post_port_sfp_firmware_info_to_db (self , mock_get_presence ):
474474 logical_port_name = "Ethernet0"
475475 port_mapping = PortMapping ()
476+ port_mapping .get_physical_to_logical = MagicMock (return_value = ["Ethernet0" , "Ethernet4" ])
476477 mock_sfp_obj_dict = MagicMock ()
477478 stop_event = threading .Event ()
478479 mock_cmis_manager = MagicMock ()
479480 dom_info_update = DomInfoUpdateTask (DEFAULT_NAMESPACE , port_mapping , mock_sfp_obj_dict , stop_event , mock_cmis_manager )
480481 firmware_info_tbl = Table ("STATE_DB" , TRANSCEIVER_FIRMWARE_INFO_TABLE )
482+
483+ # Test 1: stop_event is set - should not update table
481484 stop_event .set ()
482485 dom_info_update .post_port_sfp_firmware_info_to_db (logical_port_name , port_mapping , firmware_info_tbl , stop_event )
483486 assert firmware_info_tbl .get_size () == 0
487+
488+ # Test 2: transceiver not present - should not update table
484489 stop_event .clear ()
485490 mock_get_presence .return_value = False
486491 dom_info_update .post_port_sfp_firmware_info_to_db (logical_port_name , port_mapping , firmware_info_tbl , stop_event )
487492 assert firmware_info_tbl .get_size () == 0
493+
494+ # Test 3: transceiver present - should update table for both logical ports
488495 mock_get_presence .return_value = True
489496 dom_info_update .post_port_sfp_firmware_info_to_db (logical_port_name , port_mapping , firmware_info_tbl , stop_event )
497+ # Verify firmware info is posted for Ethernet0 (2 entries: active + inactive firmware)
490498 assert firmware_info_tbl .get_size_for_key (logical_port_name ) == 2
499+ # Verify firmware info is also posted for Ethernet4 (2 entries: active + inactive firmware)
500+ assert firmware_info_tbl .get_size_for_key ("Ethernet4" ) == 2
501+ # Verify total table has 2 logical ports (keys)
502+ assert firmware_info_tbl .get_size () == 2
503+
504+ @patch ('xcvrd.xcvrd_utilities.port_event_helper.PortMapping.logical_port_name_to_physical_port_list' , MagicMock (return_value = [0 ]))
505+ @patch ('xcvrd.xcvrd._wrapper_get_transceiver_firmware_info' , MagicMock (return_value = {'active_firmware' : '2.1.1' ,
506+ 'inactive_firmware' : '1.2.4' }))
507+ @patch ('xcvrd.xcvrd._wrapper_is_flat_memory' , MagicMock (return_value = False ))
508+ @patch ('xcvrd.xcvrd._wrapper_get_presence' )
509+ def test_post_port_sfp_firmware_info_to_db_lport_list_None (self , mock_get_presence ):
510+ logical_port_name = "Ethernet0"
511+ port_mapping = PortMapping ()
512+ port_mapping .get_physical_to_logical = MagicMock (return_value = None )
513+ port_mapping .logical_port_name_to_physical_port_list = MagicMock (return_value = [0 ])
514+ mock_sfp_obj_dict = MagicMock ()
515+ stop_event = threading .Event ()
516+ mock_cmis_manager = MagicMock ()
517+ dom_info_update = DomInfoUpdateTask (DEFAULT_NAMESPACE , port_mapping , mock_sfp_obj_dict , stop_event , mock_cmis_manager )
518+ firmware_info_tbl = MagicMock ()
519+ firmware_info_tbl .get_size .return_value = 0
520+ stop_event .set ()
521+ dom_info_update .post_port_sfp_firmware_info_to_db (logical_port_name , port_mapping , firmware_info_tbl , stop_event )
522+ assert firmware_info_tbl .get_size () == 0
523+ stop_event .clear ()
524+ mock_get_presence .return_value = False
525+ dom_info_update .post_port_sfp_firmware_info_to_db (logical_port_name , port_mapping , firmware_info_tbl , stop_event )
526+ assert firmware_info_tbl .get_size () == 0
527+ mock_get_presence .return_value = True
528+ dom_info_update .post_port_sfp_firmware_info_to_db (logical_port_name , port_mapping , firmware_info_tbl , stop_event )
529+ assert firmware_info_tbl .set .call_count == 0
491530
492531 def test_post_port_dom_sensor_info_to_db (self ):
493532 def mock_get_transceiver_dom_sensor_real_value (physical_port ):
@@ -3634,6 +3673,7 @@ def test_DomInfoUpdateTask_task_worker(self, mock_post_pm_info,
36343673 task .status_db_utils .post_port_transceiver_hw_status_to_db = MagicMock ()
36353674 task .status_db_utils .post_port_transceiver_hw_status_flags_to_db = MagicMock ()
36363675 task .vdm_utils .is_transceiver_vdm_supported = MagicMock (return_value = True )
3676+ task .xcvrd_utils .is_transceiver_lpmode_on = MagicMock (return_value = False )
36373677 task .vdm_db_utils = MagicMock ()
36383678 task .vdm_db_utils .post_port_vdm_real_values_to_db = MagicMock ()
36393679 task .task_worker ()
@@ -3698,6 +3738,7 @@ def test_DomInfoUpdateTask_task_worker_vdm_failure(self, mock_post_pm_info):
36983738 task .vdm_utils ._unfreeze_vdm_stats_and_confirm = MagicMock (return_value = True )
36993739 task .vdm_db_utils .post_port_vdm_real_values_to_db = MagicMock ()
37003740 task .vdm_db_utils .post_port_vdm_flags_to_db = MagicMock ()
3741+ task .xcvrd_utils .is_transceiver_lpmode_on = MagicMock (return_value = False )
37013742 task .task_worker ()
37023743 assert task .vdm_utils ._unfreeze_vdm_stats_and_confirm .call_count == 1
37033744 assert task .vdm_db_utils .post_port_vdm_real_values_to_db .call_count == 0
@@ -4659,6 +4700,33 @@ def test_is_transceiver_flat_memory(self):
46594700 mock_api .is_flat_memory = MagicMock (side_effect = NotImplementedError )
46604701 assert xcvrd_util .is_transceiver_flat_memory (1 )
46614702
4703+ def test_is_transceiver_lpmode_on (self ):
4704+ from xcvrd .xcvrd_utilities .utils import XCVRDUtils
4705+ mock_sfp = MagicMock ()
4706+ xcvrd_util = XCVRDUtils ({1 : mock_sfp }, MagicMock ())
4707+
4708+ # Test case where get_xcvr_api returns None
4709+ mock_sfp .get_lpmode = MagicMock (return_value = None )
4710+ assert not xcvrd_util .is_transceiver_lpmode_on (1 )
4711+
4712+ # Test case where get_lpmode returns True
4713+ mock_sfp .get_lpmode = MagicMock (return_value = True )
4714+ assert xcvrd_util .is_transceiver_lpmode_on (1 )
4715+
4716+ # Test case where get_lpmode returns False
4717+
4718+ mock_sfp .get_lpmode = MagicMock (return_value = False )
4719+ assert not xcvrd_util .is_transceiver_lpmode_on (1 )
4720+
4721+ # Test case where get_xcvr_api raises KeyError
4722+ xcvrd_util .sfp_obj_dict = {}
4723+ assert not xcvrd_util .is_transceiver_lpmode_on (1 )
4724+
4725+ # Test case where is_flat_memory raises NotImplementedError
4726+ xcvrd_util .sfp_obj_dict = {1 : mock_sfp }
4727+ mock_sfp .get_lpmode = MagicMock (side_effect = NotImplementedError )
4728+ assert not xcvrd_util .is_transceiver_lpmode_on (1 )
4729+
46624730 @patch ('time.sleep' , MagicMock ())
46634731 @patch ('xcvrd.xcvrd.XcvrTableHelper' , MagicMock ())
46644732 @patch ('xcvrd.xcvrd._wrapper_soak_sfp_insert_event' , MagicMock ())
@@ -4772,3 +4840,165 @@ def wait_until(total_wait_time, interval, call_back, *args, **kwargs):
47724840 time .sleep (interval )
47734841 wait_time += interval
47744842 return False
4843+
4844+ class TestOpticSiParser (object ):
4845+ def test_match_optics_si_key_regex_error (self ):
4846+ """Test _match_optics_si_key with invalid regex pattern (lines 31-32, 34)"""
4847+ from xcvrd .xcvrd_utilities .optics_si_parser import _match_optics_si_key
4848+
4849+ # Test with invalid regex pattern that causes re.error
4850+ dict_key = "[invalid regex" # Unclosed bracket causes regex error
4851+ key = "VENDOR-1234"
4852+ vendor_name_str = "VENDOR"
4853+
4854+ # Should fall back to string comparison and return True for exact match
4855+ result = _match_optics_si_key (dict_key , key , vendor_name_str )
4856+ assert result == False # No exact string match
4857+
4858+ # Test with exact string match after regex error
4859+ result = _match_optics_si_key (dict_key , dict_key , vendor_name_str )
4860+ assert result == True # Exact string match
4861+
4862+ def test_match_optics_si_key_fallback_string_match (self ):
4863+ """Test _match_optics_si_key fallback string comparison (line 37)"""
4864+ from xcvrd .xcvrd_utilities .optics_si_parser import _match_optics_si_key
4865+
4866+ # Test with invalid regex that falls back to string comparison
4867+ dict_key = "[invalid"
4868+ key = "VENDOR-1234"
4869+ vendor_name_str = "VENDOR"
4870+
4871+ # Test exact key match
4872+ result = _match_optics_si_key (key , key , vendor_name_str )
4873+ assert result == True
4874+
4875+ # Test vendor name match
4876+ result = _match_optics_si_key (vendor_name_str , key , vendor_name_str )
4877+ assert result == True
4878+
4879+ # Test split key match
4880+ result = _match_optics_si_key ("VENDOR" , key , vendor_name_str )
4881+ assert result == True
4882+
4883+ def test_get_port_media_settings_speed_key_missing (self ):
4884+ """Test _get_port_media_settings when SPEED_KEY not in optics_si_dict (line 126)"""
4885+ from xcvrd .xcvrd_utilities .optics_si_parser import _get_port_media_settings
4886+ import xcvrd .xcvrd_utilities .optics_si_parser as parser
4887+
4888+ original_dict = parser .g_optics_si_dict
4889+ parser .g_optics_si_dict = {
4890+ 'PORT_MEDIA_SETTINGS' : {
4891+ '5' : {
4892+ # Missing SPEED_KEY (25G_SPEED)
4893+ }
4894+ }
4895+ }
4896+
4897+ try :
4898+ result = _get_port_media_settings (5 , 25 , "VENDOR-1234" , "VENDOR" , {'default' : 'value' })
4899+ assert result == {'default' : 'value' }
4900+ finally :
4901+ parser .g_optics_si_dict = original_dict
4902+
4903+ def test_get_module_vendor_key_api_none (self ):
4904+ """Test get_module_vendor_key when API is None (line 152)"""
4905+ from xcvrd .xcvrd_utilities .optics_si_parser import get_module_vendor_key
4906+
4907+ # Mock SFP with None API
4908+ mock_sfp = MagicMock ()
4909+ mock_sfp .get_xcvr_api .return_value = None
4910+
4911+ result = get_module_vendor_key (1 , mock_sfp )
4912+ assert result is None
4913+
4914+ def test_get_module_vendor_key_vendor_name_none (self ):
4915+ """Test get_module_vendor_key when vendor name is None"""
4916+ from xcvrd .xcvrd_utilities .optics_si_parser import get_module_vendor_key
4917+
4918+ # Mock API with None vendor name
4919+ mock_api = MagicMock ()
4920+ mock_api .get_manufacturer .return_value = None
4921+ mock_sfp = MagicMock ()
4922+ mock_sfp .get_xcvr_api .return_value = mock_api
4923+
4924+ result = get_module_vendor_key (1 , mock_sfp )
4925+ assert result is None
4926+
4927+ def test_get_module_vendor_key_vendor_pn_none (self ):
4928+ """Test get_module_vendor_key when vendor part number is None"""
4929+ from xcvrd .xcvrd_utilities .optics_si_parser import get_module_vendor_key
4930+
4931+ # Mock API with None vendor part number
4932+ mock_api = MagicMock ()
4933+ mock_api .get_manufacturer .return_value = "VENDOR"
4934+ mock_api .get_model .return_value = None
4935+ mock_sfp = MagicMock ()
4936+ mock_sfp .get_xcvr_api .return_value = mock_api
4937+
4938+ result = get_module_vendor_key (1 , mock_sfp )
4939+ assert result is None
4940+
4941+ def test_get_port_media_settings_no_values_with_empty_default (self ):
4942+ """Test _get_port_media_settings logging when port exists but has empty config and no default values"""
4943+ from xcvrd .xcvrd_utilities .optics_si_parser import _get_port_media_settings
4944+ import xcvrd .xcvrd_utilities .optics_si_parser as parser
4945+
4946+ original_dict = parser .g_optics_si_dict
4947+
4948+ # Set up scenario where:
4949+ # 1. Port exists in PORT_MEDIA_SETTINGS but has empty configuration
4950+ # 2. This makes len(optics_si_dict) == 0
4951+ # 3. Default dict is empty (len(default_dict) == 0)
4952+ parser .g_optics_si_dict = {
4953+ 'PORT_MEDIA_SETTINGS' : {
4954+ '5' : {} # Port exists but is empty - this triggers len(optics_si_dict) == 0
4955+ }
4956+ }
4957+
4958+ try :
4959+ # This should trigger the log_info line at lines 119-121
4960+ # since len(optics_si_dict) == 0 and len(default_dict) == 0
4961+ result = _get_port_media_settings (5 , 25 , "VENDOR-1234" , "VENDOR" , {})
4962+
4963+ # Should return empty dict when no values found and no defaults
4964+ assert result == {}
4965+ finally :
4966+ parser .g_optics_si_dict = original_dict
4967+
4968+ def test_load_optics_si_settings_no_file (self ):
4969+ """Test load_optics_si_settings when no file exists"""
4970+ from xcvrd .xcvrd_utilities .optics_si_parser import load_optics_si_settings
4971+
4972+ with patch ('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs' ,
4973+ return_value = ('/nonexistent/platform' , '/nonexistent/hwsku' )):
4974+ with patch ('os.path.isfile' , return_value = False ):
4975+ result = load_optics_si_settings ()
4976+ assert result == {}
4977+
4978+ def test_optics_si_present_empty_dict (self ):
4979+ """Test optics_si_present when global dict is empty"""
4980+ from xcvrd .xcvrd_utilities .optics_si_parser import optics_si_present
4981+ import xcvrd .xcvrd_utilities .optics_si_parser as parser
4982+
4983+ original_dict = parser .g_optics_si_dict
4984+ parser .g_optics_si_dict = {}
4985+
4986+ try :
4987+ result = optics_si_present ()
4988+ assert result == False
4989+ finally :
4990+ parser .g_optics_si_dict = original_dict
4991+
4992+ def test_optics_si_present_with_data (self ):
4993+ """Test optics_si_present when global dict has data"""
4994+ from xcvrd .xcvrd_utilities .optics_si_parser import optics_si_present
4995+ import xcvrd .xcvrd_utilities .optics_si_parser as parser
4996+
4997+ original_dict = parser .g_optics_si_dict
4998+ parser .g_optics_si_dict = {'some' : 'data' }
4999+
5000+ try :
5001+ result = optics_si_present ()
5002+ assert result == True
5003+ finally :
5004+ parser .g_optics_si_dict = original_dict
0 commit comments