-- 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 method_misc = require('method_misc')
local common_def = require('common_def')

TestMethodMisc = {}

function TestMethodMisc:test_check_read_policy()
    local ret
    local read_policy, type_id = 3, common_def.PMC_3152_8I_SMART_RAID - 1
    ret = method_misc:check_read_policy(read_policy, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)

    read_policy, type_id = 3, common_def.PMC_3152_8I_SMART_RAID
    ret = method_misc:check_read_policy(read_policy, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)

    read_policy, type_id = 3, common_def.HI1880_SP186_M_16i
    ret = method_misc:check_read_policy(read_policy, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)

    read_policy, type_id = 1, common_def.PMC_3152_8I_SMART_RAID - 1
    ret = method_misc:check_read_policy(read_policy, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_SUCCESS)

    read_policy, type_id = 3, common_def.HRDT_B261s
    ret = method_misc:check_read_policy(read_policy, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)
end

function TestMethodMisc:test_check_boot_devices_count()
    local ret
    local method_misc = require('method_misc')
    local common_def = require('common_def')
    local lu = require('luaunit')

    -- 测试1: 非华为厂商控制器 => 应该返回 SUCCESS
    local controller_obj = {
        TypeId = common_def.PMC_3152_8I_SMART_RAID,
        SupportedBootDeviceCount = 2,
        BootDevices = { 'Disk1', 'Disk2' },
    }
    ret = method_misc:check_boot_devices_count(common_def.BOOT_PRIORITY_PRIMARY, controller_obj)
    lu.assertEquals(ret, common_def.SM_CODE_SUCCESS)

    -- 测试2: 华为厂商但 boot_priority 不是 PRIMARY => 应该返回 SUCCESS
    controller_obj = {
        TypeId = common_def.HI1880_SP186_M_16i,
        SupportedBootDeviceCount = 2,
        BootDevices = { 'Disk1', 'Disk2' },
    }
    ret = method_misc:check_boot_devices_count(common_def.BOOT_PRIORITY_SECONDARY, controller_obj)
    lu.assertEquals(ret, common_def.SM_CODE_SUCCESS)

    -- 测试3: 华为厂商但 SupportedBootDeviceCount <= 1 => 应该返回 SUCCESS
    controller_obj = {
        TypeId = common_def.HI1880_SP186_M_16i,
        SupportedBootDeviceCount = 1,
        BootDevices = { 'Disk1' },
    }
    ret = method_misc:check_boot_devices_count(common_def.BOOT_PRIORITY_PRIMARY, controller_obj)
    lu.assertEquals(ret, common_def.SM_CODE_SUCCESS)

    -- 测试4: BootDevices 数量未达到上限 => 应该返回 SUCCESS
    controller_obj = {
        TypeId = common_def.HI1880_SP186_M_16i,
        SupportedBootDeviceCount = 5,
        BootDevices = { 'Disk1', 'None', 'None', 'None', 'None' }, -- 只有1个有效设备
    }
    ret = method_misc:check_boot_devices_count(common_def.BOOT_PRIORITY_PRIMARY, controller_obj)
    lu.assertEquals(ret, common_def.SM_CODE_SUCCESS)

    -- 测试5: BootDevices 数量已达到上限 => 应该返回 ILLEGAL
    controller_obj = {
        TypeId = common_def.HI1880_SP186_M_16i,
        SupportedBootDeviceCount = 5,
        BootDevices = { 'Disk1', 'Disk2', 'Disk3', 'Disk4', 'Disk5' }, -- 已达到上限
    }
    ret = method_misc:check_boot_devices_count(common_def.BOOT_PRIORITY_PRIMARY, controller_obj)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)

    -- 测试6: BootDevices 全是 None => 应该返回 SUCCESS
    controller_obj = {
        TypeId = common_def.HI1880_SP186_M_16i,
        SupportedBootDeviceCount = 5,
        BootDevices = { 'None', 'None', 'None', 'None', 'None' }, -- 没有有效设备
    }
    ret = method_misc:check_boot_devices_count(common_def.BOOT_PRIORITY_PRIMARY, controller_obj)
    lu.assertEquals(ret, common_def.SM_CODE_SUCCESS)

    -- 测试7: BootDevices 混合有效设备 => 只计数有效设备
    controller_obj = {
        TypeId = common_def.HI1880_SP186_M_16i,
        SupportedBootDeviceCount = 5,
        BootDevices = { 'Disk1', 'Volume1', 'Disk2', 'Volume2', 'Disk3' }, -- 已达到上限
    }
    ret = method_misc:check_boot_devices_count(common_def.BOOT_PRIORITY_PRIMARY, controller_obj)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)
end

function TestMethodMisc:test_check_recheck_io_policyad_policy()
    local ret
    local io_policy, type_id = 3, common_def.PMC_3152_8I_SMART_RAID - 1
    ret = method_misc:check_io_policy(io_policy, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)

    io_policy, type_id = 3, common_def.PMC_3152_8I_SMART_RAID
    ret = method_misc:check_io_policy(io_policy, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)

    io_policy, type_id = 3, common_def.HI1880_SP186_M_16i
    ret = method_misc:check_io_policy(io_policy, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)

    io_policy, type_id = 1, common_def.PMC_3152_8I_SMART_RAID - 1
    ret = method_misc:check_io_policy(io_policy, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_SUCCESS)

    io_policy, type_id = 3, common_def.HRDT_B261s
    ret = method_misc:check_io_policy(io_policy, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)
end

function TestMethodMisc:test_check_access_policy()
    local ret
    local access_policy, type_id = 3, common_def.PMC_3152_8I_SMART_RAID - 1
    ret = method_misc:check_access_policy(access_policy, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)

    access_policy, type_id = 3, common_def.PMC_3152_8I_SMART_RAID
    ret = method_misc:check_access_policy(access_policy, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)

    access_policy, type_id = 3, common_def.HI1880_SP186_M_16i
    ret = method_misc:check_access_policy(access_policy, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)

    access_policy, type_id = 1, common_def.PMC_3152_8I_SMART_RAID - 1
    ret = method_misc:check_access_policy(access_policy, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_SUCCESS)

    access_policy, type_id = 3, common_def.HRDT_B261s
    ret = method_misc:check_access_policy(access_policy, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)
end

function TestMethodMisc:test_check_BGI()
    local ret
    local BGI_enable, type_id = 3, common_def.PMC_3152_8I_SMART_RAID - 1
    ret = method_misc:check_BGI(BGI_enable, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)

    BGI_enable, type_id = 3, common_def.PMC_3152_8I_SMART_RAID
    ret = method_misc:check_BGI(BGI_enable, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)

    BGI_enable, type_id = 3, common_def.HI1880_SP186_M_16i
    ret = method_misc:check_BGI(BGI_enable, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)

    BGI_enable, type_id = 1, common_def.PMC_3152_8I_SMART_RAID - 1
    ret = method_misc:check_BGI(BGI_enable, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_SUCCESS)

    BGI_enable, type_id = 3, common_def.HRDT_B261s
    ret = method_misc:check_BGI(BGI_enable, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)
end

function TestMethodMisc:test_get_manufacturer_name_by_oui()
    local ret
    local unknown_oui = 'XXXXXX'
    ret = method_misc:get_manufacturer_name_by_oui(unknown_oui)
    lu.assertEquals(ret, 'ATA')

    local ym_oui = 'A428B7'
    ret = method_misc:get_manufacturer_name_by_oui(ym_oui)
    lu.assertEquals(ret, 'YANGTZE MEMORY')
end

-- 使用 stub client 并重载 method_misc,确保 method_misc 内部使用的是我们注入的 client
local function with_stub_client_and_method_misc(add_fn, delete_fn, run)
    local old_client = package.loaded['storage.client']
    local old_misc = package.loaded['method_misc']
    local stub_client = {
        PFirmwareInventoryFirmwareInventoryAdd = add_fn or function()
            return true, nil
        end,
        PFirmwareInventoryFirmwareInventoryDelete = delete_fn or function()
            return true, nil
        end,
    }
    package.loaded['storage.client'] = stub_client
    package.loaded['method_misc'] = nil
    local method_misc_reload = require('method_misc')
    local ok, err = pcall(run, method_misc_reload)
    package.loaded['method_misc'] = old_misc
    package.loaded['storage.client'] = old_client
    if not ok then
        error(err)
    end
end

-- 测试retry_register_firmware_info成功场景
function TestMethodMisc:test_retry_register_firmware_info_success()
    local skynet = require('skynet')
    local context = require('mc.context')
    local call_count = 0
    local fork_called = false
    local callback_called = false
    local old_fork = skynet.fork
    local old_sleep = skynet.sleep
    local old_context_new = context.new
    skynet.fork = function(func)
        fork_called = true
        func()
    end
    skynet.sleep = function(ticks) end
    context.new = function()
        return {}
    end
    with_stub_client_and_method_misc(
        function(self, ctx, param, updateable, capability, max_package_size_mib)
            call_count = call_count + 1
            return true, nil
        end,
        nil,
        function(method_misc_reload)
            local firmware_info_table = {
                Id = 'Drive1-Firmware',
                Name = 'Drive1 Firmware',
                Version = '1.0.0',
            }
            local success_callback = function()
                callback_called = true
            end
            method_misc_reload:retry_register_firmware_info(firmware_info_table, true, 0x01, 100, success_callback)
            lu.assertEquals(fork_called, true)
            lu.assertEquals(call_count, 1)
            lu.assertEquals(callback_called, true)
        end
    )
    skynet.fork = old_fork
    skynet.sleep = old_sleep
    context.new = old_context_new
end

-- 测试retry_register_firmware_info重试场景
function TestMethodMisc:test_retry_register_firmware_info_retry()
    local skynet = require('skynet')
    local context = require('mc.context')
    local call_count = 0
    local sleep_count = 0
    local old_fork = skynet.fork
    local old_sleep = skynet.sleep
    local old_context_new = context.new
    skynet.fork = function(func)
        func()
    end
    skynet.sleep = function(ticks)
        sleep_count = sleep_count + 1
    end
    context.new = function()
        return {}
    end
    with_stub_client_and_method_misc(
        function(self, ctx, param, updateable, capability, max_package_size_mib)
            call_count = call_count + 1
            if call_count < 3 then
                return false, 'error'
            end
            return true, nil
        end,
        nil,
        function(method_misc_reload)
            local firmware_info_table = {
                Id = 'Drive1-Firmware',
                Version = '1.0.0',
            }
            method_misc_reload:retry_register_firmware_info(firmware_info_table, true, 0x01, 100)
            lu.assertEquals(call_count, 3)
            lu.assertEquals(sleep_count, 2)
        end
    )
    skynet.fork = old_fork
    skynet.sleep = old_sleep
    context.new = old_context_new
end

-- 测试retry_register_firmware_info失败场景
function TestMethodMisc:test_retry_register_firmware_info_fail()
    local skynet = require('skynet')
    local context = require('mc.context')
    local call_count = 0
    local sleep_count = 0
    local old_fork = skynet.fork
    local old_sleep = skynet.sleep
    local old_context_new = context.new
    skynet.fork = function(func)
        func()
    end
    skynet.sleep = function(ticks)
        sleep_count = sleep_count + 1
    end
    context.new = function()
        return {}
    end
    with_stub_client_and_method_misc(
        function(self, ctx, param, updateable, capability, max_package_size_mib)
            call_count = call_count + 1
            return false, 'always fail'
        end,
        nil,
        function(method_misc_reload)
            local firmware_info_table = {
                Id = 'Drive1-Firmware',
                Version = '1.0.0',
            }
            method_misc_reload:retry_register_firmware_info(firmware_info_table, true, 0x01, 100)
            lu.assertEquals(call_count, 3)
            lu.assertEquals(sleep_count, 2)
        end
    )
    skynet.fork = old_fork
    skynet.sleep = old_sleep
    context.new = old_context_new
end

-- 测试retry_register_firmware_info转发FirmwareType字段(RAID固件类型上送)
function TestMethodMisc:test_retry_register_firmware_info_forward_firmware_type()
    local skynet = require('skynet')
    local context = require('mc.context')
    local captured_param
    local old_fork = skynet.fork
    local old_context_new = context.new
    skynet.fork = function(func)
        func()
    end
    context.new = function()
        return {}
    end
    with_stub_client_and_method_misc(
        function(self, ctx, param)
            captured_param = param
            return true, nil
        end,
        nil,
        function(method_misc_reload)
            local firmware_info_table = {
                Id = 'RAIDCard1',
                Version = '1.0.0',
                FirmwareType = 'Raid',
            }
            method_misc_reload:retry_register_firmware_info(firmware_info_table, true, 0x01, 100)
            lu.assertNotNil(captured_param)
            lu.assertEquals(captured_param.FirmwareType, 'Raid')
        end
    )
    skynet.fork = old_fork
    context.new = old_context_new
end

-- 测试retry_register_firmware_info未携带FirmwareType时默认填空串(硬盘等既有注册行为不变)
function TestMethodMisc:test_retry_register_firmware_info_default_firmware_type()
    local skynet = require('skynet')
    local context = require('mc.context')
    local captured_param
    local old_fork = skynet.fork
    local old_context_new = context.new
    skynet.fork = function(func)
        func()
    end
    context.new = function()
        return {}
    end
    with_stub_client_and_method_misc(
        function(self, ctx, param)
            captured_param = param
            return true, nil
        end,
        nil,
        function(method_misc_reload)
            local firmware_info_table = {
                Id = 'Drive1-Firmware',
                Version = '1.0.0',
            }
            method_misc_reload:retry_register_firmware_info(firmware_info_table, true, 0x01, 100)
            lu.assertNotNil(captured_param)
            lu.assertEquals(captured_param.FirmwareType, '')
            lu.assertEquals(captured_param.Model, '')
        end
    )
    skynet.fork = old_fork
    context.new = old_context_new
end

-- 测试retry_register_firmware_info转发Model字段(硬盘型号上送)
function TestMethodMisc:test_retry_register_firmware_info_forward_model()
    local skynet = require('skynet')
    local context = require('mc.context')
    local captured_param
    local old_fork = skynet.fork
    local old_context_new = context.new
    skynet.fork = function(func)
        func()
    end
    context.new = function()
        return {}
    end
    with_stub_client_and_method_misc(
        function(self, ctx, param)
            captured_param = param
            return true, nil
        end,
        nil,
        function(method_misc_reload)
            local firmware_info_table = {
                Id = 'HDDPlaneDisk0',
                Version = '3012',
                Model = 'HSSD-Test-Model',
            }
            method_misc_reload:retry_register_firmware_info(firmware_info_table, true, 0x01, 100)
            lu.assertNotNil(captured_param)
            lu.assertEquals(captured_param.Model, 'HSSD-Test-Model')
        end
    )
    skynet.fork = old_fork
    context.new = old_context_new
end

-- 测试retry_unregister_firmware_info成功场景
function TestMethodMisc:test_retry_unregister_firmware_info_success()
    local skynet = require('skynet')
    local context = require('mc.context')
    local call_count = 0
    local fork_called = false
    local callback_called = false
    local old_fork = skynet.fork
    local old_sleep = skynet.sleep
    local old_context_new = context.new
    skynet.fork = function(func)
        fork_called = true
        func()
    end
    skynet.sleep = function(ticks) end
    context.new = function()
        return {}
    end
    with_stub_client_and_method_misc(nil, function(self, ctx, firmware_id)
        call_count = call_count + 1
        return true, nil
    end, function(method_misc_reload)
        local success_callback = function()
            callback_called = true
        end
        method_misc_reload:retry_unregister_firmware_info('Drive1-Firmware', success_callback)
        lu.assertEquals(fork_called, true)
        lu.assertEquals(call_count, 1)
        lu.assertEquals(callback_called, true)
    end)
    skynet.fork = old_fork
    skynet.sleep = old_sleep
    context.new = old_context_new
end

-- 测试retry_unregister_firmware_info重试场景
function TestMethodMisc:test_retry_unregister_firmware_info_retry()
    local skynet = require('skynet')
    local context = require('mc.context')
    local call_count = 0
    local sleep_count = 0
    local old_fork = skynet.fork
    local old_sleep = skynet.sleep
    local old_context_new = context.new
    skynet.fork = function(func)
        func()
    end
    skynet.sleep = function(ticks)
        sleep_count = sleep_count + 1
    end
    context.new = function()
        return {}
    end
    with_stub_client_and_method_misc(nil, function(self, ctx, firmware_id)
        call_count = call_count + 1
        if call_count < 2 then
            return false, 'error'
        end
        return true, nil
    end, function(method_misc_reload)
        method_misc_reload:retry_unregister_firmware_info('Drive1-Firmware')
        lu.assertEquals(call_count, 2)
        lu.assertEquals(sleep_count, 1)
    end)
    skynet.fork = old_fork
    skynet.sleep = old_sleep
    context.new = old_context_new
end

-- 测试retry_unregister_firmware_info失败场景
function TestMethodMisc:test_retry_unregister_firmware_info_fail()
    local skynet = require('skynet')
    local context = require('mc.context')
    local call_count = 0
    local sleep_count = 0
    local old_fork = skynet.fork
    local old_sleep = skynet.sleep
    local old_context_new = context.new
    skynet.fork = function(func)
        func()
    end
    skynet.sleep = function(ticks)
        sleep_count = sleep_count + 1
    end
    context.new = function()
        return {}
    end
    with_stub_client_and_method_misc(nil, function(self, ctx, firmware_id)
        call_count = call_count + 1
        return false, 'always fail'
    end, function(method_misc_reload)
        method_misc_reload:retry_unregister_firmware_info('Drive1-Firmware')
        lu.assertEquals(call_count, 3)
        lu.assertEquals(sleep_count, 2)
    end)
    skynet.fork = old_fork
    skynet.sleep = old_sleep
    context.new = old_context_new
end

-- 测试update_firmware_info成功场景
function TestMethodMisc:test_update_firmware_info_success()
    local skynet = require('skynet')
    local mdb = require('mc.mdb')
    local object_manage = require('mc.orm.object_manage')
    local fork_called = false

    local old_fork_once = skynet.fork_once
    local old_get_cached_object = mdb.get_cached_object
    local old_get_instance = object_manage.get_instance

    skynet.fork_once = function(func)
        fork_called = true
        func()
    end

    object_manage.get_instance = function()
        return {
            bus = 'mock_bus',
        }
    end

    mdb.get_cached_object = function(bus, path, interface)
        return {
            Version = '0.0.0',
        }
    end

    local firmware_obj = {
        NodeId = 'node1',
        Name = 'Test Firmware',
    }

    method_misc:update_firmware_info(firmware_obj, '2.0.0')
    lu.assertEquals(fork_called, true)
    skynet.fork_once = old_fork_once
    mdb.get_cached_object = old_get_cached_object
    object_manage.get_instance = old_get_instance
end

function TestMethodMisc:test_update_firmware_info_retry()
    local skynet = require('skynet')
    local mdb = require('mc.mdb')
    local object_manage = require('mc.orm.object_manage')
    local fork_called = false
    local sleep_count = 0

    local old_fork_once = skynet.fork_once
    local old_get_cached_object = mdb.get_cached_object
    local old_get_instance = object_manage.get_instance
    local old_sleep = skynet.sleep

    skynet.fork_once = function(func)
        fork_called = true
        func()
    end

    skynet.sleep = function(ticks)
        sleep_count = sleep_count + 1
    end
    object_manage.get_instance = function()
        return {
            bus = 'mock_bus',
        }
    end

    mdb.get_cached_object = function(bus, path, interface)
        return false
    end

    local firmware_obj = {
        NodeId = 'node1',
        Name = 'Test Firmware',
    }

    method_misc:update_firmware_info(firmware_obj, '2.0.0')
    lu.assertEquals(sleep_count, 2)
    lu.assertEquals(fork_called, true)
    skynet.fork_once = old_fork_once
    mdb.get_cached_object = old_get_cached_object
    object_manage.get_instance = old_get_instance
    skynet.sleep = old_sleep
end

-- Covers lines 81, 175, 208: elseif branches in check_io_policy, check_BGI, check_access_policy with unknown vendor
function TestMethodMisc:test_check_io_policy_unknown_vendor_returns_success()
    local ret = method_misc:check_io_policy(5, 300)
    lu.assertEquals(ret, common_def.SM_CODE_SUCCESS)
end

function TestMethodMisc:test_check_BGI_unknown_vendor_returns_success()
    local ret = method_misc:check_BGI(5, 300)
    lu.assertEquals(ret, common_def.SM_CODE_SUCCESS)
end

function TestMethodMisc:test_check_access_policy_unknown_vendor_returns_success()
    local ret = method_misc:check_access_policy(5, 300)
    lu.assertEquals(ret, common_def.SM_CODE_SUCCESS)
end

-- Covers line 231: get_ld_name_max_length with LSI vendor
function TestMethodMisc:test_get_ld_name_max_length_lsi()
    local ret = method_misc:get_ld_name_max_length(common_def.PMC_3152_8I_SMART_RAID - 1)
    lu.assertEquals(ret, 15)
end

-- Covers lines for PMC and Huawei and unknown in get_ld_name_max_length
function TestMethodMisc:test_get_ld_name_max_length_all_vendors()
    lu.assertEquals(method_misc:get_ld_name_max_length(common_def.PMC_3152_8I_SMART_RAID), 64)
    lu.assertEquals(method_misc:get_ld_name_max_length(common_def.HI1880_SP186_M_16i), 20)
    lu.assertEquals(method_misc:get_ld_name_max_length(300), 0)
end

-- Covers line 245: check_ld_name_too_long with LSI vendor and len > SL_LD_NAME_LENGTH
function TestMethodMisc:test_check_ld_name_too_long_lsi_exceeds()
    local ret =
        method_misc:check_ld_name_too_long(common_def.SL_LD_NAME_LENGTH + 1, common_def.PMC_3152_8I_SMART_RAID - 1)
    lu.assertTrue(ret)
end

-- Covers other branches of check_ld_name_too_long
function TestMethodMisc:test_check_ld_name_too_long_all_vendors()
    -- LSI within limit
    lu.assertFalse(
        method_misc:check_ld_name_too_long(common_def.SL_LD_NAME_LENGTH, common_def.PMC_3152_8I_SMART_RAID - 1)
    )
    -- PMC exceeds
    lu.assertTrue(
        method_misc:check_ld_name_too_long(common_def.SC_LD_NAME_LENGTH + 1, common_def.PMC_3152_8I_SMART_RAID)
    )
    -- Huawei exceeds
    lu.assertTrue(method_misc:check_ld_name_too_long(common_def.HS_LD_NAME_LENGTH + 1, common_def.HI1880_SP186_M_16i))
    -- Unknown vendor
    lu.assertFalse(method_misc:check_ld_name_too_long(999, 300))
end

-- Covers check_string_is_valid_ascii
function TestMethodMisc:test_check_string_is_valid_ascii()
    lu.assertTrue(method_misc:check_string_is_valid_ascii('abcXYZ123'))
    lu.assertFalse(method_misc:check_string_is_valid_ascii('abc\x01def'))
end

-- Covers check_volume_name
function TestMethodMisc:test_check_volume_name()
    -- valid name within length and valid ASCII
    lu.assertEquals(
        method_misc:check_volume_name('valid', common_def.PMC_3152_8I_SMART_RAID - 1),
        common_def.SM_CODE_SUCCESS
    )
    -- name too long for LSI
    lu.assertEquals(
        method_misc:check_volume_name(
            string.rep('a', common_def.SL_LD_NAME_LENGTH + 1),
            common_def.PMC_3152_8I_SMART_RAID - 1
        ),
        common_def.SM_CODE_LD_NAME_EXCEED_MAX_LEN
    )
    -- name with invalid ASCII
    lu.assertEquals(
        method_misc:check_volume_name('ab\x01cd', common_def.PMC_3152_8I_SMART_RAID - 1),
        common_def.SM_CODE_LD_NAME_INVALID_ASCII
    )
end

-- Covers get_oob_interface_type
function TestMethodMisc:test_get_oob_interface_type()
    lu.assertEquals(method_misc:get_oob_interface_type(common_def.HI1880_SP186_M_16i), common_def.OOB_TYPE_OVER_PCIE)
    lu.assertEquals(
        method_misc:get_oob_interface_type(common_def.PMC_3152_8I_SMART_RAID),
        common_def.OOB_TYPE_OVER_PCIE
    )
    lu.assertEquals(
        method_misc:get_oob_interface_type(common_def.PMC_3152_8I_SMART_RAID - 1),
        common_def.OOB_TYPE_OVER_I2C
    )
    lu.assertEquals(method_misc:get_oob_interface_type(300), common_def.INVALID_U8)
end

-- Covers check_is_suport_upgrade
function TestMethodMisc:test_check_is_suport_upgrade()
    lu.assertTrue(method_misc:check_is_suport_upgrade(common_def.HI1880_SP686C_M_16i_2G))
    lu.assertFalse(method_misc:check_is_suport_upgrade(200))
end

-- Covers test_controller_oob_support
function TestMethodMisc:test_test_controller_oob_support()
    lu.assertTrue(method_misc:test_controller_oob_support(1))
    lu.assertFalse(method_misc:test_controller_oob_support(10))
end

-- Covers get_boot_priority_op_desc
function TestMethodMisc:test_get_boot_priority_op_desc()
    local ret =
        method_misc:get_boot_priority_op_desc(common_def.BOOT_PRIORITY_PRIMARY, common_def.PMC_3152_8I_SMART_RAID - 1)
    lu.assertEquals(ret, common_def.AS_BOOT_DEVICE)
    local ret2 = method_misc:get_boot_priority_op_desc(common_def.BOOT_PRIORITY_PRIMARY, 300)
    lu.assertEquals(ret2, common_def.INVALID_STRING)
end

-- Covers check_boot_priority_param
function TestMethodMisc:test_check_boot_priority_param()
    lu.assertEquals(
        method_misc:check_boot_priority_param(
            common_def.BOOT_PRIORITY_PRIMARY + 1,
            common_def.PMC_3152_8I_SMART_RAID - 1
        ),
        common_def.SM_CODE_PARA_DATA_ILLEGAL
    )
    lu.assertEquals(
        method_misc:check_boot_priority_param(common_def.BOOT_PRIORITY_PRIMARY, common_def.PMC_3152_8I_SMART_RAID - 1),
        common_def.SM_CODE_SUCCESS
    )
    lu.assertEquals(
        method_misc:check_boot_priority_param(common_def.BOOT_PRIORITY_PRIMARY, 200),
        common_def.SM_CODE_SUCCESS
    )
end

-- Covers remove_ele_by_position
function TestMethodMisc:test_remove_ele_by_position()
    local list = { { position = 1 }, { position = 2 }, { position = 3 } }
    method_misc:remove_ele_by_position(list, 2)
    lu.assertEquals(#list, 2)
    lu.assertEquals(list[2].position, 3)
end

-- Covers update_if_valid
function TestMethodMisc:test_update_if_valid()
    lu.assertEquals(method_misc:update_if_valid(0, 1, 99), 1)
    lu.assertEquals(method_misc:update_if_valid(0, 0, 99), 99)
    lu.assertEquals(method_misc:update_if_valid(0, nil, 99), 99)
end
function TestMethodMisc:test_check_boot_priority_param_hrdt()
    local ret
    local boot_priority = 4
    local type_id = common_def.HRDT_B261s
    ret = method_misc:check_boot_priority_param(boot_priority, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_PARA_DATA_ILLEGAL)

    boot_priority = 3
    ret = method_misc:check_boot_priority_param(boot_priority, type_id)
    lu.assertEquals(ret, common_def.SM_CODE_SUCCESS)
end

function TestMethodMisc:test_get_boot_priority_op_desc_hrdt()
    local ret
    ret = method_misc:get_boot_priority_op_desc(1, common_def.HRDT_B261s)
    lu.assertEquals(ret, 'boot priority to Primary')
end

function TestMethodMisc:test_get_ld_name_max_length_hrdt()
    local ret = method_misc:get_ld_name_max_length(common_def.HRDT_B261s)
    lu.assertEquals(ret, 20)
end

function TestMethodMisc:test_check_ld_name_too_long_hrdt()
    local ret
    ret = method_misc:check_ld_name_too_long(21, common_def.HRDT_B261s)
    lu.assertEquals(ret, true)

    ret = method_misc:check_ld_name_too_long(20, common_def.HRDT_B261s)
    lu.assertEquals(ret, false)
end

function TestMethodMisc:test_get_oob_interface_type_hrdt()
    local ret = method_misc:get_oob_interface_type(common_def.HRDT_B261s)
    lu.assertEquals(ret, common_def.OOB_TYPE_OVER_I2C)
end

function TestMethodMisc:test_test_controller_vendor_hrdt()
    local ret
    ret = method_misc:test_controller_vendor(common_def.HRDT_B261s, common_def.VENDER_HRDT)
    lu.assertEquals(ret, true)

    ret = method_misc:test_controller_vendor(common_def.HRDT_B261s, common_def.VENDER_LSI)
    lu.assertEquals(ret, false)
end