Skip to content

Commit 1584d10

Browse files
committed
2 parents 7a9aa82 + c6f5f57 commit 1584d10

2 files changed

Lines changed: 108 additions & 0 deletions

File tree

sonic-xcvrd/tests/test_xcvrd.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4354,6 +4354,108 @@ def test_is_transceiver_flat_memory(self):
43544354
mock_api.is_flat_memory = MagicMock(side_effect=NotImplementedError)
43554355
assert xcvrd_util.is_transceiver_flat_memory(1)
43564356

4357+
@patch('time.sleep', MagicMock())
4358+
@patch('xcvrd.xcvrd.XcvrTableHelper', MagicMock())
4359+
@patch('xcvrd.xcvrd._wrapper_soak_sfp_insert_event', MagicMock())
4360+
@patch('xcvrd.xcvrd_utilities.port_event_helper.subscribe_port_config_change', MagicMock(return_value=(None, None)))
4361+
@patch('xcvrd.xcvrd_utilities.port_event_helper.handle_port_config_change', MagicMock())
4362+
@patch('xcvrd.xcvrd.SfpStateUpdateTask.init', MagicMock())
4363+
@patch('os.kill')
4364+
@patch('xcvrd.xcvrd.SfpStateUpdateTask._mapping_event_from_change_event')
4365+
@patch('xcvrd.xcvrd._wrapper_get_transceiver_change_event')
4366+
@patch('xcvrd.xcvrd.del_port_sfp_dom_info_from_db')
4367+
@patch('xcvrd.xcvrd_utilities.media_settings_parser.notify_media_setting')
4368+
@patch('xcvrd.dom.dom_mgr.DomInfoUpdateTask.post_port_sfp_firmware_info_to_db')
4369+
@patch('xcvrd.xcvrd.post_port_sfp_info_to_db')
4370+
@patch('xcvrd.xcvrd.update_port_transceiver_status_table_sw')
4371+
@patch('xcvrd.xcvrd.platform_chassis')
4372+
def test_sfp_removal_from_dict(self, mock_platform_chassis, mock_update_status, mock_post_sfp_info,
4373+
mock_post_firmware_info, mock_update_media_setting,
4374+
mock_del_dom, mock_change_event, mock_mapping_event, mock_os_kill):
4375+
port_mapping = PortMapping()
4376+
mock_sfp = MagicMock()
4377+
mock_sfp.remove_xcvr_api = MagicMock(return_value=None)
4378+
mock_platform_chassis.get_sfp.return_value = mock_sfp
4379+
mock_sfp_obj_dict = MagicMock()
4380+
stop_event = threading.Event()
4381+
sfp_error_event = threading.Event()
4382+
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, mock_sfp_obj_dict, stop_event, sfp_error_event)
4383+
task.xcvr_table_helper = XcvrTableHelper(DEFAULT_NAMESPACE)
4384+
task.dom_db_utils.post_port_dom_thresholds_to_db = MagicMock()
4385+
task.vdm_db_utils.post_port_vdm_thresholds_to_db = MagicMock()
4386+
mock_change_event.return_value = (True, {0: 0}, {})
4387+
mock_mapping_event.return_value = SYSTEM_NOT_READY
4388+
4389+
# Test state machine: STATE_INIT + SYSTEM_NOT_READY event => STATE_INIT + SYSTEM_NOT_READY event ... => STATE_EXIT
4390+
task.task_worker(stop_event, sfp_error_event)
4391+
assert mock_os_kill.call_count == 1
4392+
assert sfp_error_event.is_set()
4393+
4394+
mock_mapping_event.return_value = SYSTEM_FAIL
4395+
mock_os_kill.reset_mock()
4396+
sfp_error_event.clear()
4397+
# Test state machine: STATE_INIT + SYSTEM_FAIL event => STATE_INIT + SYSTEM_FAIL event ... => STATE_EXIT
4398+
task.task_worker(stop_event, sfp_error_event)
4399+
assert mock_os_kill.call_count == 1
4400+
assert sfp_error_event.is_set()
4401+
4402+
mock_mapping_event.side_effect = [SYSTEM_BECOME_READY, SYSTEM_NOT_READY]
4403+
mock_os_kill.reset_mock()
4404+
sfp_error_event.clear()
4405+
# Test state machine: STATE_INIT + SYSTEM_BECOME_READY event => STATE_NORMAL + SYSTEM_NOT_READY event ... => STATE_EXIT
4406+
task.task_worker(stop_event, sfp_error_event)
4407+
assert mock_os_kill.call_count == 1
4408+
assert not sfp_error_event.is_set()
4409+
4410+
mock_mapping_event.side_effect = [SYSTEM_BECOME_READY, SYSTEM_FAIL] + \
4411+
[SYSTEM_FAIL] * (RETRY_TIMES_FOR_SYSTEM_READY + 1)
4412+
mock_os_kill.reset_mock()
4413+
sfp_error_event.clear()
4414+
# Test state machine: STATE_INIT + SYSTEM_BECOME_READY event => STATE_NORMAL + SYSTEM_FAIL event ... => STATE_INIT
4415+
# + SYSTEM_FAIL event ... => STATE_EXIT
4416+
task.task_worker(stop_event, sfp_error_event)
4417+
assert mock_os_kill.call_count == 1
4418+
assert sfp_error_event.is_set()
4419+
4420+
task.port_mapping.handle_port_change_event(PortChangeEvent('Ethernet0', 1, 0, PortChangeEvent.PORT_ADD))
4421+
mock_change_event.return_value = (True, {1: SFP_STATUS_INSERTED}, {})
4422+
mock_mapping_event.side_effect = None
4423+
mock_mapping_event.return_value = NORMAL_EVENT
4424+
mock_post_sfp_info.return_value = SFP_EEPROM_NOT_READY
4425+
stop_event.is_set = MagicMock(side_effect=[False, True])
4426+
# Test state machine: handle SFP insert event, but EEPROM read failure
4427+
task.task_worker(stop_event, sfp_error_event)
4428+
assert mock_update_status.call_count == 1
4429+
assert mock_post_sfp_info.call_count == 2 # first call and retry call
4430+
assert task.dom_db_utils.post_port_dom_thresholds_to_db.call_count == 0
4431+
assert task.vdm_db_utils.post_port_vdm_thresholds_to_db.call_count == 0
4432+
assert mock_post_firmware_info.call_count == 0
4433+
assert mock_update_media_setting.call_count == 0
4434+
assert 'Ethernet0' in task.retry_eeprom_set
4435+
task.retry_eeprom_set.clear()
4436+
4437+
stop_event.is_set = MagicMock(side_effect=[False, True])
4438+
mock_post_sfp_info.return_value = None
4439+
mock_update_status.reset_mock()
4440+
mock_post_sfp_info.reset_mock()
4441+
# Test state machine: handle SFP insert event, and EEPROM read success
4442+
task.task_worker(stop_event, sfp_error_event)
4443+
assert mock_update_status.call_count == 1
4444+
assert mock_post_sfp_info.call_count == 1
4445+
assert task.dom_db_utils.post_port_dom_thresholds_to_db.call_count == 1
4446+
assert task.vdm_db_utils.post_port_vdm_thresholds_to_db.call_count == 1
4447+
assert mock_post_firmware_info.call_count == 0
4448+
assert mock_update_media_setting.call_count == 1
4449+
4450+
stop_event.is_set = MagicMock(side_effect=[False, True])
4451+
mock_change_event.return_value = (True, {1: SFP_STATUS_REMOVED}, {})
4452+
mock_update_status.reset_mock()
4453+
# Test state machine: handle SFP remove event
4454+
task.task_worker(stop_event, sfp_error_event)
4455+
assert mock_update_status.call_count == 1
4456+
assert mock_del_dom.call_count == 1
4457+
mock_sfp.remove_xcvr_api.assert_called_once()
4458+
43574459
def wait_until(total_wait_time, interval, call_back, *args, **kwargs):
43584460
wait_time = 0
43594461
while wait_time <= total_wait_time:

sonic-xcvrd/xcvrd/xcvrd.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1686,6 +1686,12 @@ def task_worker(self, stopping_event, sfp_error_event):
16861686
media_settings_parser.notify_media_setting(logical_port, transceiver_dict, self.xcvr_table_helper, self.port_mapping)
16871687
transceiver_dict.clear()
16881688
elif value == sfp_status_helper.SFP_STATUS_REMOVED:
1689+
# Remove the SFP API object for this physical port
1690+
try:
1691+
sfp = platform_chassis.get_sfp(int(key))
1692+
sfp.remove_xcvr_api()
1693+
except (NotImplementedError, AttributeError) as e:
1694+
helper_logger.log_error(f"Failed to remove xcvr api for port {key}: {str(e)}")
16891695
helper_logger.log_notice("{}: Got SFP removed event".format(logical_port))
16901696
state_port_table = self.xcvr_table_helper.get_state_port_tbl(asic_index)
16911697
state_port_table.set(logical_port, [(NPU_SI_SETTINGS_SYNC_STATUS_KEY, NPU_SI_SETTINGS_DEFAULT_VALUE)])

0 commit comments

Comments
 (0)