From ef486c5e6c633e5256f97743d06f6af4e6185b0f Mon Sep 17 00:00:00 2001 From: Junchao-Mellanox Date: Fri, 8 Sep 2023 14:53:36 +0800 Subject: [PATCH 1/3] Support new API sfp.dump_eeprom --- sonic_platform_base/sfp_base.py | 12 +++ .../sonic_xcvr/api/public/cmis.py | 11 ++- .../sonic_xcvr/api/public/sff8436.py | 3 + .../sonic_xcvr/api/public/sff8472.py | 24 +++++- .../sonic_xcvr/api/public/sff8636.py | 3 + .../sonic_xcvr/api/xcvr_api.py | 67 ++++++++++++++++ .../sonic_xcvr/sfp_optoe_base.py | 13 ++++ tests/sonic_xcvr/test_cmis.py | 51 ++++++++++++ tests/sonic_xcvr/test_sff8472.py | 77 ++++++++++++++++--- 9 files changed, 245 insertions(+), 16 deletions(-) diff --git a/sonic_platform_base/sfp_base.py b/sonic_platform_base/sfp_base.py index 804b51ab8..dd468f79d 100644 --- a/sonic_platform_base/sfp_base.py +++ b/sonic_platform_base/sfp_base.py @@ -451,6 +451,18 @@ def get_error_description(self): """ raise NotImplementedError + def dump_eeprom(self, page=None): + """ + Dump all EEPROM data for this SFP + + Args: + page: EEPROM page number, dump all pages if page is None + + Returns: + A string contains the hex format EEPROM data + """ + raise NotImplementedError + def refresh_xcvr_api(self): """ Updates the XcvrApi associated with this SFP diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmis.py b/sonic_platform_base/sonic_xcvr/api/public/cmis.py index a677f32ff..54fe7f26f 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmis.py @@ -763,10 +763,10 @@ def get_media_lane_count(self, appl=1): ''' if self.is_flat_memory(): return 0 - + if (appl <= 0): return 0 - + appl_advt = self.get_application_advertisement() return appl_advt[appl]['media_lane_count'] if len(appl_advt) >= appl else 0 @@ -795,10 +795,10 @@ def get_media_lane_assignment_option(self, appl=1): ''' if self.is_flat_memory(): return 'N/A' - + if (appl <= 0): return 0 - + appl_advt = self.get_application_advertisement() return appl_advt[appl]['media_lane_assignment_options'] if len(appl_advt) >= appl else 0 @@ -2438,4 +2438,7 @@ def get_error_description(self): return None + def _get_valid_eeprom_pages(self): + return (0, 1, 2, 16, 17) if not self.is_flat_memory() else (0,) + # TODO: other XcvrApi methods diff --git a/sonic_platform_base/sonic_xcvr/api/public/sff8436.py b/sonic_platform_base/sonic_xcvr/api/public/sff8436.py index 4336cf6f0..e53300859 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/sff8436.py +++ b/sonic_platform_base/sonic_xcvr/api/public/sff8436.py @@ -351,3 +351,6 @@ def get_lpmode(self): # Since typically optics come up by default set to high power, in this case, # power_override not being set, function will return high power mode. return power_set and power_override + + def _get_valid_eeprom_pages(self): + return (0, 1, 2, 3) if not self.is_flat_memory() else (0,) diff --git a/sonic_platform_base/sonic_xcvr/api/public/sff8472.py b/sonic_platform_base/sonic_xcvr/api/public/sff8472.py index 36e458d3a..ba737be87 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/sff8472.py +++ b/sonic_platform_base/sonic_xcvr/api/public/sff8472.py @@ -37,7 +37,7 @@ def get_transceiver_info(self): if len > 0: cable_len = len cable_type = type - + xcvr_info = { "type": serial_id[consts.ID_FIELD], "type_abbrv_name": serial_id[consts.ID_ABBRV_FIELD], @@ -295,3 +295,25 @@ def get_lpmode_support(self): def get_power_override_support(self): return False + + def is_active_cable(self): + return self.xcvr_eeprom.read(consts.SFP_CABLE_TECH_FIELD) == 'Active Cable' + + def _get_valid_eeprom_pages(self): + return (0, 1) if self.is_active_cable() else (0,) + + def _dump_eeprom_pages(self, pages): + indent = ' ' * 8 + lines = [] + for page in pages: + if page == 0: + if self.is_active_cable(): + lines.append(f'{indent}A0h dump') + lines.append(self._dump_eeprom(0, 256, 0, indent)) + else: + lines.append(f'{indent}A0h dump') + lines.append(self._dump_eeprom(0, 128, 0, indent)) + elif page == 1: + lines.append(f'\n{indent}A2h dump (lower 128 bytes)') + lines.append(self._dump_eeprom(256, 128, 0, indent)) + return '\n'.join(lines) diff --git a/sonic_platform_base/sonic_xcvr/api/public/sff8636.py b/sonic_platform_base/sonic_xcvr/api/public/sff8636.py index f59163a6c..307be19b8 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/sff8636.py +++ b/sonic_platform_base/sonic_xcvr/api/public/sff8636.py @@ -403,3 +403,6 @@ def get_lpmode(self): # Since typically optics come up by default set to high power, in this case, # power_override not being set, function will return high power mode. return power_set and power_override + + def _get_valid_eeprom_pages(self): + return (0, 1, 2, 3) if not self.is_flat_memory() else (0,) diff --git a/sonic_platform_base/sonic_xcvr/api/xcvr_api.py b/sonic_platform_base/sonic_xcvr/api/xcvr_api.py index eaaed35da..59a35e4d9 100644 --- a/sonic_platform_base/sonic_xcvr/api/xcvr_api.py +++ b/sonic_platform_base/sonic_xcvr/api/xcvr_api.py @@ -637,3 +637,70 @@ def get_error_description(self): """ raise NotImplementedError + def convert_byte_to_valid_ascii_char(self, byte): + if byte < 32 or 126 < byte: + return '.' + else: + return chr(byte) + + def hexdump(self, indent, data, mem_address): + size = len(data) + offset = 0 + lines = [] + while size > 0: + offset_str = "{}{:08x}".format(indent, mem_address) + if size >= 16: + first_half = ' '.join("{:02x}".format(x) for x in data[offset:offset + 8]) + second_half = ' '.join("{:02x}".format(x) for x in data[offset + 8:offset + 16]) + ascii_str = ''.join(self.convert_byte_to_valid_ascii_char(x) for x in data[offset:offset + 16]) + lines.append(f'{offset_str} {first_half} {second_half} |{ascii_str}|') + elif size > 8: + first_half = ' '.join("{:02x}".format(x) for x in data[offset:offset + 8]) + second_half = ' '.join("{:02x}".format(x) for x in data[offset + 8:offset + size]) + padding = ' ' * (16 - size) + ascii_str = ''.join(self.convert_byte_to_valid_ascii_char(x) for x in data[offset:offset + size]) + lines.append(f'{offset_str} {first_half} {second_half}{padding} |{ascii_str}|') + break + else: + hex_part = ' '.join("{:02x}".format(x) for x in data[offset:offset + size]) + padding = ' ' * (16 - size) + ascii_str = ''.join(self.convert_byte_to_valid_ascii_char(x) for x in data[offset:offset + size]) + lines.append(f'{offset_str} {hex_part} {padding} |{ascii_str}|') + break + size -= 16 + offset += 16 + mem_address += 16 + return '\n'.join(lines) + + def dump_eeprom(self, page): + pages = self._get_valid_eeprom_pages() + if page is not None: + if page not in pages: + raise ValueError(f"Invalid page {page}") + pages = (page,) + return self._dump_eeprom_pages(pages) + + def _dump_eeprom_pages(self, pages): + indent = ' ' * 8 + lines = [] + for page in pages: + if page == 0: + lines.append(f'{indent}Lower page 0h') + lines.append(self._dump_eeprom(0, 128, 0, indent)) + lines.append(f'\n{indent}Upper page 0h') + lines.append(self._dump_eeprom(128, 128, 128, indent)) + else: + lines.append(f'\n{indent}Page {page}h') + lines.append(self._dump_eeprom(256 + (page - 1) * 128, 128, 128, indent)) + return '\n'.join(lines) + + def _get_valid_eeprom_pages(self): + raise NotImplementedError + + def _dump_eeprom(self, overall_offset, size, page_offset, indent): + page_dump = self.xcvr_eeprom.read_raw(overall_offset, size, return_raw=True) + if page_dump is None: + return f'{indent}N/A' + + output = self.hexdump(indent, page_dump, page_offset) + return output diff --git a/sonic_platform_base/sonic_xcvr/sfp_optoe_base.py b/sonic_platform_base/sonic_xcvr/sfp_optoe_base.py index 668389e14..c7ae8514f 100644 --- a/sonic_platform_base/sonic_xcvr/sfp_optoe_base.py +++ b/sonic_platform_base/sonic_xcvr/sfp_optoe_base.py @@ -213,3 +213,16 @@ def get_error_description(self): """ api = self.get_xcvr_api() return api.get_error_description() if api is not None else None + + def dump_eeprom(self, page=None): + """ + Dump all EEPROM data for this SFP + + Args: + page: EEPROM page number, dump all pages if page is None + + Returns: + A string contains the hex format EEPROM data + """ + api = self.get_xcvr_api() + return api.dump_eeprom(page) if api is not None else None diff --git a/tests/sonic_xcvr/test_cmis.py b/tests/sonic_xcvr/test_cmis.py index 5b072deb8..6293f9c8a 100644 --- a/tests/sonic_xcvr/test_cmis.py +++ b/tests/sonic_xcvr/test_cmis.py @@ -2371,3 +2371,54 @@ def test_get_transceiver_info_firmware_versions_negative_tests(self): self.api.get_module_fw_info.side_effect = {'result': TypeError} result = self.api.get_transceiver_info_firmware_versions() assert result == ["N/A", "N/A"] + + def test_dump_eeprom(self): + with pytest.raises(ValueError): + self.api.dump_eeprom(-1) + + self.api.xcvr_eeprom.read_raw = MagicMock() + self.api.xcvr_eeprom.read_raw.side_effect = [bytearray([x for x in range(128)]), bytearray([x for x in range(128, 256)])] + output = self.api.dump_eeprom(0) + expected_output = """ Lower page 0h + 00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................| + 00000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................| + 00000020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f | !"#$%&'()*+,-./| + 00000030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f |0123456789:;<=>?| + 00000040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f |@ABCDEFGHIJKLMNO| + 00000050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f |PQRSTUVWXYZ[\]^_| + 00000060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f |`abcdefghijklmno| + 00000070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f |pqrstuvwxyz{|}~.| + + Upper page 0h + 00000080 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f |................| + 00000090 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f |................| + 000000a0 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af |................| + 000000b0 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf |................| + 000000c0 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf |................| + 000000d0 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df |................| + 000000e0 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef |................| + 000000f0 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff |................|""" + assert output == expected_output + + self.api.xcvr_eeprom.read_raw.reset_mock(return_value=True, side_effect=True) + self.api.xcvr_eeprom.read_raw.return_value = bytearray([x for x in range(128)]) + output = self.api.dump_eeprom(1) + expected_output = """ + Page 1h + 00000080 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................| + 00000090 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................| + 000000a0 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f | !"#$%&'()*+,-./| + 000000b0 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f |0123456789:;<=>?| + 000000c0 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f |@ABCDEFGHIJKLMNO| + 000000d0 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f |PQRSTUVWXYZ[\]^_| + 000000e0 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f |`abcdefghijklmno| + 000000f0 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f |pqrstuvwxyz{|}~.|""" + assert output == expected_output + + self.api.xcvr_eeprom.read_raw.return_value = None + output = self.api.dump_eeprom(1) + print(output) + expected_output = """ + Page 1h + N/A""" + assert output == expected_output diff --git a/tests/sonic_xcvr/test_sff8472.py b/tests/sonic_xcvr/test_sff8472.py index a1d8c1a2c..2fb698c3b 100644 --- a/tests/sonic_xcvr/test_sff8472.py +++ b/tests/sonic_xcvr/test_sff8472.py @@ -22,7 +22,7 @@ class TestSff8472(object): def test_api(self): """ - Verify all api access valid fields + Verify all api access valid fields """ self.api.get_model() self.api.get_serial() @@ -61,7 +61,7 @@ def test_temp(self): data = bytearray([0x80, 0x00]) deps = { consts.INT_CAL_FIELD: True, - consts.EXT_CAL_FIELD: False, + consts.EXT_CAL_FIELD: False, consts.T_SLOPE_FIELD: 1, consts.T_OFFSET_FIELD: 0, } @@ -71,7 +71,7 @@ def test_temp(self): data = bytearray([0x0F, 0xFF]) deps = { consts.INT_CAL_FIELD: False, - consts.EXT_CAL_FIELD: True, + consts.EXT_CAL_FIELD: True, consts.T_SLOPE_FIELD: 2, consts.T_OFFSET_FIELD: 10, } @@ -83,7 +83,7 @@ def test_voltage(self): data = bytearray([0xFF, 0xFF]) deps = { consts.INT_CAL_FIELD: True, - consts.EXT_CAL_FIELD: False, + consts.EXT_CAL_FIELD: False, consts.T_SLOPE_FIELD: 1, consts.T_OFFSET_FIELD: 0, } @@ -94,7 +94,7 @@ def test_voltage(self): data = bytearray([0x7F, 0xFF]) deps = { consts.INT_CAL_FIELD: False, - consts.EXT_CAL_FIELD: True, + consts.EXT_CAL_FIELD: True, consts.V_SLOPE_FIELD: 2, consts.V_OFFSET_FIELD: 10, } @@ -106,7 +106,7 @@ def test_tx_bias(self): data = bytearray([0xFF, 0xFF]) deps = { consts.INT_CAL_FIELD: True, - consts.EXT_CAL_FIELD: False, + consts.EXT_CAL_FIELD: False, consts.TX_I_SLOPE_FIELD: 1, consts.TX_I_OFFSET_FIELD: 0, } @@ -117,7 +117,7 @@ def test_tx_bias(self): data = bytearray([0x7F, 0xFF]) deps = { consts.INT_CAL_FIELD: False, - consts.EXT_CAL_FIELD: True, + consts.EXT_CAL_FIELD: True, consts.TX_I_SLOPE_FIELD: 2, consts.TX_I_OFFSET_FIELD: 10, } @@ -129,7 +129,7 @@ def test_tx_power(self): data = bytearray([0xFF, 0xFF]) deps = { consts.INT_CAL_FIELD: True, - consts.EXT_CAL_FIELD: False, + consts.EXT_CAL_FIELD: False, consts.TX_PWR_SLOPE_FIELD: 1, consts.TX_PWR_OFFSET_FIELD: 0, } @@ -140,7 +140,7 @@ def test_tx_power(self): data = bytearray([0x7F, 0xFF]) deps = { consts.INT_CAL_FIELD: False, - consts.EXT_CAL_FIELD: True, + consts.EXT_CAL_FIELD: True, consts.TX_PWR_SLOPE_FIELD: 2, consts.TX_PWR_OFFSET_FIELD: 10, } @@ -152,7 +152,7 @@ def test_rx_power(self): data = bytearray([0xFF, 0xFF]) deps = { consts.INT_CAL_FIELD: True, - consts.EXT_CAL_FIELD: False, + consts.EXT_CAL_FIELD: False, consts.RX_PWR_0_FIELD: 0, consts.RX_PWR_1_FIELD: 1, consts.RX_PWR_2_FIELD: 0, @@ -165,7 +165,7 @@ def test_rx_power(self): deps = { consts.INT_CAL_FIELD: False, - consts.EXT_CAL_FIELD: True, + consts.EXT_CAL_FIELD: True, consts.RX_PWR_0_FIELD: 10, consts.RX_PWR_1_FIELD: 2, consts.RX_PWR_2_FIELD: 0.1, @@ -289,3 +289,58 @@ def test_get_transceiver_bulk_status(self, mock_response, expected): result = self.api.get_transceiver_bulk_status() assert result == expected + def test_dump_eeprom(self): + with pytest.raises(ValueError): + self.api.dump_eeprom(-1) + + self.api.is_active_cable = MagicMock(return_value=False) + self.api.xcvr_eeprom.read_raw = MagicMock() + self.api.xcvr_eeprom.read_raw.return_value = bytearray([x for x in range(128)]) + output = self.api.dump_eeprom(0) + expected_output = """ A0h dump + 00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................| + 00000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................| + 00000020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f | !"#$%&'()*+,-./| + 00000030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f |0123456789:;<=>?| + 00000040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f |@ABCDEFGHIJKLMNO| + 00000050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f |PQRSTUVWXYZ[\]^_| + 00000060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f |`abcdefghijklmno| + 00000070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f |pqrstuvwxyz{|}~.|""" + assert output == expected_output + + self.api.is_active_cable.return_value = True + self.api.xcvr_eeprom.read_raw.return_value = bytearray([x for x in range(256)]) + output = self.api.dump_eeprom(0) + expected_output = """ A0h dump + 00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................| + 00000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................| + 00000020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f | !"#$%&'()*+,-./| + 00000030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f |0123456789:;<=>?| + 00000040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f |@ABCDEFGHIJKLMNO| + 00000050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f |PQRSTUVWXYZ[\]^_| + 00000060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f |`abcdefghijklmno| + 00000070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f |pqrstuvwxyz{|}~.| + 00000080 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f |................| + 00000090 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f |................| + 000000a0 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af |................| + 000000b0 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf |................| + 000000c0 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf |................| + 000000d0 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df |................| + 000000e0 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef |................| + 000000f0 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff |................|""" + assert output == expected_output + + self.api.xcvr_eeprom.read_raw.return_value = bytearray([x for x in range(128)]) + output = self.api.dump_eeprom(1) + print(output) + expected_output = """ + A2h dump (lower 128 bytes) + 00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................| + 00000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................| + 00000020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f | !"#$%&'()*+,-./| + 00000030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f |0123456789:;<=>?| + 00000040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f |@ABCDEFGHIJKLMNO| + 00000050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f |PQRSTUVWXYZ[\]^_| + 00000060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f |`abcdefghijklmno| + 00000070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f |pqrstuvwxyz{|}~.|""" + assert output == expected_output From 1b1cf4a54f37262230c1e9587dd3693c6ac97d12 Mon Sep 17 00:00:00 2001 From: Junchao-Mellanox Date: Wed, 27 Sep 2023 12:21:31 +0300 Subject: [PATCH 2/3] Fix unit test failure --- tests/sonic_xcvr/test_cmis.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/sonic_xcvr/test_cmis.py b/tests/sonic_xcvr/test_cmis.py index 6293f9c8a..8f1b334c9 100644 --- a/tests/sonic_xcvr/test_cmis.py +++ b/tests/sonic_xcvr/test_cmis.py @@ -2376,6 +2376,7 @@ def test_dump_eeprom(self): with pytest.raises(ValueError): self.api.dump_eeprom(-1) + self.api.is_flat_memory = MagicMock(return_value=False) self.api.xcvr_eeprom.read_raw = MagicMock() self.api.xcvr_eeprom.read_raw.side_effect = [bytearray([x for x in range(128)]), bytearray([x for x in range(128, 256)])] output = self.api.dump_eeprom(0) From 6fa938fec7b4bb86945b25320772d98b662b6f29 Mon Sep 17 00:00:00 2001 From: Junchao-Mellanox Date: Tue, 10 Oct 2023 11:41:03 +0300 Subject: [PATCH 3/3] Increate code coverage --- tests/sonic_xcvr/test_cmis.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/sonic_xcvr/test_cmis.py b/tests/sonic_xcvr/test_cmis.py index 8f1b334c9..47cdcc24a 100644 --- a/tests/sonic_xcvr/test_cmis.py +++ b/tests/sonic_xcvr/test_cmis.py @@ -2372,6 +2372,37 @@ def test_get_transceiver_info_firmware_versions_negative_tests(self): result = self.api.get_transceiver_info_firmware_versions() assert result == ["N/A", "N/A"] + def test_hex_dump(self): + data = bytearray([x for x in range(128)]) + output = self.api.hexdump(' ' * 8, data, 0) + expected_output = """ 00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................| + 00000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................| + 00000020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f | !"#$%&'()*+,-./| + 00000030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f |0123456789:;<=>?| + 00000040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f |@ABCDEFGHIJKLMNO| + 00000050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f |PQRSTUVWXYZ[\]^_| + 00000060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f |`abcdefghijklmno| + 00000070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f |pqrstuvwxyz{|}~.|""" + assert output == expected_output + + data = bytearray([x for x in range(23)]) + output = self.api.hexdump(' ' * 8, data, 0) + expected_output = """ 00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................| + 00000010 10 11 12 13 14 15 16 |.......|""" + assert output == expected_output + + data = bytearray([x for x in range(24)]) + output = self.api.hexdump(' ' * 8, data, 0) + expected_output = """ 00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................| + 00000010 10 11 12 13 14 15 16 17 |........|""" + assert output == expected_output + + data = bytearray([x for x in range(25)]) + output = self.api.hexdump(' ' * 8, data, 0) + expected_output = """ 00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................| + 00000010 10 11 12 13 14 15 16 17 18 |.........|""" + assert output == expected_output + def test_dump_eeprom(self): with pytest.raises(ValueError): self.api.dump_eeprom(-1)