-- Copyright (c) 2025 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.

local lu = require 'luaunit'
local bs = require 'mc.bitstring'
local cmd_handler = require 'debug.cmd_handler'

TEST_debug_cmd = {}

function TEST_debug_cmd:setUp()
    self.original_bs_new = bs.new
    
    -- 打桩 bs.new
    bs.new = function(pattern)
        local obj = {}
        function obj:unpack(data, flag)
            return {
                response_code = 0,
                reason_code = 0,
                extended_speed_duplex = 1,
                link_flag = 1,
                speed_duplex = 5,
                negotiate_flag = 1,
                pci_vid = 0x19e5,
                pci_did = 0x0222,
                pci_svid = 0x19e5,
                pci_ssid = 0x0051,
                firmware_version_1 = 1,
                firmware_version_2 = 2,
                firmware_version_3 = 3,
                ncsi_version_major = 0x10,
                ncsi_version_minor = 0x20,
                ncsi_version_update = 0xFF,
                ncsi_version_alpha1 = 65,
                ncsi_version_alpha2 = 66
            }
        end
        return obj
    end
end

function TEST_debug_cmd:tearDown()
    bs.new = self.original_bs_new
end

function TEST_debug_cmd:test_handlers_table_exists()
    lu.assertNotNil(cmd_handler.handlers)
    lu.assertEquals(type(cmd_handler.handlers), 'table')
    lu.assertNotNil(cmd_handler.handlers[0x0A])
    lu.assertNotNil(cmd_handler.handlers[0x15])
end

function TEST_debug_cmd:test_link_status_handler_success()
    local mock_port = {
        NodeId = 'TestPort1',
        package_id = 1,
        ncsi_config_obj = {
            Test = function(self, params)
                lu.assertEquals(params.channel_id, 2)
                lu.assertEquals(params.package_id, 1)
                lu.assertEquals(params.packet_type, 0x0A)
                lu.assertEquals(params.expect_rsp_packet_type, 0x8A)
                return {
                    value = function() return 'mock_response_data' end
                }
            end
        },
        get_port_id = function(self) return 2 end
    }
    
    local result = cmd_handler.handlers[0x0A](mock_port)
    
    lu.assertNotNil(result)
    lu.assertTrue(string.find(result, 'LinkStatus:Connected') ~= nil)
    lu.assertTrue(string.find(result, 'SpeedMbps:100') ~= nil)
end

function TEST_debug_cmd:test_vendor_info_handler_success()
    local mock_card = {
        NodeId = 'TestCard1',
        package_id = 2,
        ncsi_config_obj = {
            Test = function(self, params)
                lu.assertEquals(params.package_id, 2)
                lu.assertEquals(params.packet_type, 0x15)
                lu.assertEquals(params.expect_rsp_packet_type, 0x95)
                lu.assertEquals(params.channel_id, 0x0)
                return {
                    value = function() return 'mock_vendor_data' end
                }
            end
        }
    }
    
    local result = cmd_handler.handlers[0x15](mock_card)
    
    lu.assertNotNil(result)
    lu.assertTrue(string.find(result, 'FirmwareVersion:01.02.0003') ~= nil)
    lu.assertTrue(string.find(result, 'VendorID:0x19e5') ~= nil)
    lu.assertTrue(string.find(result, 'DeviceID:0x0222') ~= nil)
end

function TEST_debug_cmd:test_link_status_extended_speed()
    local mock_port = {
        NodeId = 'TestPort2',
        package_id = 1,
        ncsi_config_obj = {
            Test = function(self, params)
                return {
                    value = function() return 'mock_response_data' end
                }
            end
        },
        get_port_id = function(self) return 1 end
    }
    
    -- 临时打桩扩展速度场景
    local temp_original = bs.new
    bs.new = function(pattern)
        local obj = {}
        function obj:unpack(data, flag)
            return {
                response_code = 0,
                reason_code = 0,
                extended_speed_duplex = 17,
                link_flag = 1,
                speed_duplex = 0xF,
                negotiate_flag = 0
            }
        end
        return obj
    end
    
    local result = cmd_handler.handlers[0x0A](mock_port)
    
    lu.assertNotNil(result)
    lu.assertTrue(string.find(result, 'SpeedMbps:200000') ~= nil)
    lu.assertTrue(string.find(result, 'AutoSpeedNegotiation:false') ~= nil)
    
    bs.new = temp_original
end

function TEST_debug_cmd:test_link_status_disconnected()
    local mock_port = {
        NodeId = 'TestPort3',
        package_id = 1,
        ncsi_config_obj = {
            Test = function(self, params)
                return {
                    value = function() return 'mock_response_data' end
                }
            end
        },
        get_port_id = function(self) return 1 end
    }
    
    -- 临时打桩断开连接场景
    local temp_original = bs.new
    bs.new = function(pattern)
        local obj = {}
        function obj:unpack(data, flag)
            return {
                link_flag = 0,
                speed_duplex = 1,
                negotiate_flag = 1
            }
        end
        return obj
    end
    
    local result = cmd_handler.handlers[0x0A](mock_port)
    
    lu.assertTrue(string.find(result, 'LinkStatus:Disconnected') ~= nil)
    
    bs.new = temp_original
end

function TEST_debug_cmd:test_bsd_to_string_high_nibble_f()
    -- 测试高4位为0xF的情况
    local temp_original = bs.new
    bs.new = function(pattern)
        local obj = {}
        function obj:unpack(data, flag)
            return {
                firmware_version_1 = 0xF5,
                firmware_version_2 = 2,
                firmware_version_3 = 3
            }
        end
        return obj
    end
    
    local mock_card = {
        NodeId = 'TestCard1',
        package_id = 1,
        ncsi_config_obj = {
            Test = function(self, params)
                return {
                    value = function() return 'mock_data' end
                }
            end
        }
    }
    
    local result = cmd_handler.handlers[0x15](mock_card)
    lu.assertTrue(string.find(result, 'FirmwareVersion:245.02.0003') ~= nil)
    
    bs.new = temp_original
end

function TEST_debug_cmd:test_bsd_to_string_less_than_16()
    -- 测试小于0x10的情况
    local temp_original = bs.new
    bs.new = function(pattern)
        local obj = {}
        function obj:unpack(data, flag)
            return {
                firmware_version_1 = 5,
                firmware_version_2 = 8,
                firmware_version_3 = 100
            }
        end
        return obj
    end
    
    local mock_card = {
        NodeId = 'TestCard2',
        package_id = 1,
        ncsi_config_obj = {
            Test = function(self, params)
                return {
                    value = function() return 'mock_data' end
                }
            end
        }
    }
    
    local result = cmd_handler.handlers[0x15](mock_card)
    lu.assertTrue(string.find(result, 'FirmwareVersion:05.08.0100') ~= nil)
    
    bs.new = temp_original
end

function TEST_debug_cmd:test_bsd_to_string_bcd_conversion()
    -- 测试BCD转换情况
    local temp_original = bs.new
    bs.new = function(pattern)
        local obj = {}
        function obj:unpack(data, flag)
            return {
                firmware_version_1 = 0x23,
                firmware_version_2 = 0x45,
                firmware_version_3 = 678
            }
        end
        return obj
    end
    
    local mock_card = {
        NodeId = 'TestCard3',
        package_id = 1,
        ncsi_config_obj = {
            Test = function(self, params)
                return {
                    value = function() return 'mock_data' end
                }
            end
        }
    }
    
    local result = cmd_handler.handlers[0x15](mock_card)
    print('BCD test result:', result)
    lu.assertTrue(string.find(result, 'FirmwareVersion:20.40.0678') ~= nil)
    
    bs.new = temp_original
end

