local lu = require 'luaunit'
local c_drive = require 'drive.drive_object'
local c_storageconfig = require 'storageconfig.storageconfig_object'

local hook_tasks = require 'hook_tasks'

TEST_Drive_Object = {}

function TEST_Drive_Object:setUp()
    self.tasks = hook_tasks:hook()
end

function TEST_Drive_Object:tearDown()
    hook_tasks.unhook()
end

function TEST_Drive_Object:test_monitor_fault_state()
    local config = c_storageconfig.new({bus = 0, db = 1})
    config.all_ctrl_loaded = false
    local obj = {
        new_task = function(...) return {
            loop = function(obj, cb)
                cb(1)
                return {set_timeout_ms = function(...) return end}
            end
        } end,
        Protocol = 3,
        RefControllerId = 0,
        Presence = 0,
        LocateLed = 0,
        FaultLed = 1,
        InAFailedArray = 2,
        cont_bin = {
            get_debounced_val = function(i, n) return n end,
            clear_debounced_val = function() end
        },
        FirmwareStatusError = true
    }
    c_drive.monitor_fault_state(obj)
    lu.assertEquals(obj.InAFailedArray, 1)
    obj.Presence = 1
    c_drive.monitor_fault_state(obj)
    lu.assertEquals(obj.InAFailedArray, 0)
end

function TEST_Drive_Object:test_nvme_identified()
    local config = c_storageconfig.new({bus = 0, db = 1})
    config.all_ctrl_loaded = false
    local obj = {
        process_when_nvme_removed = function(nvme_obj)
            nvme_obj.SerialNumber = 'test'
        end
    }
    c_drive.nvme_identified(obj)
    lu.assertEquals(obj.SerialNumber, 'test')
end

function TEST_Drive_Object:test_nvme_identified_with_object()
    local config = c_storageconfig.new({bus = 0, db = 1})
    local init_nvme_flag = false
    local update_smart_info = false
    config.all_ctrl_loaded = false
    local obj = {
        update_by_mctp = function ()
            init_nvme_flag = true
        end,
        update_dynamic_info = function ()
        end,
        update_nvme_smart_log_info = function ()
        end,
        update_subhealth_info_from_mctp = function ()
            update_smart_info = true
        end,
        new_task = function(...) return {
            loop = function(obj, cb)
                task = {
                    stop = function()
                    end
                }
                cb(task)
                return {set_timeout_ms = function(...) return end}
            end
        } end
    }
    local mock_nvme = {
        protocol = 0,
        init_nvme_mi_mctp = function()
            return true
        end
    }
    c_drive.nvme_identified(obj, mock_nvme)
    lu.assertTrue(init_nvme_flag, "通过MCTP更新信息")
    c_drive.update_by_mctp(obj, mock_nvme)
    lu.assertTrue(update_smart_info, "更新subhealth")
end

-- 测试nvme_static_identified函数 - 全量覆盖
function TEST_Drive_Object:test_nvme_static_identified_with_nvme_object()
    -- 测试用例1：nvme对象存在且identify_pd为false的情况
    local task_created = false
    local task_loop_executed = false
    local static_info_updated = false
    local asset_info_updated = false
    local timeout_set_correctly = false

    local mock_nvme = {
        -- 模拟nvme对象
        slot = 1,
        model = "Test NVMe"
    }

    local task_obj = {}
    local obj = {
        ObjectName = "TestDrive",
        identify_pd = false,
        new_task = function(self, task_name)
            task_created = true
            lu.assertEquals(task_name[1], 'update_nvme_static')
            lu.assertEquals(task_name[2], "TestDrive")
            return task_obj
        end
    }

    -- 为task_obj添加loop方法
    task_obj.loop = function(self, callback)
        task_loop_executed = true
        -- 执行回调函数测试内部逻辑
        callback()
        return self -- 返回自身以支持链式调用
    end

    -- 为task_obj添加set_timeout_ms方法
    task_obj.set_timeout_ms = function(self, timeout)
        timeout_set_correctly = (timeout == 120000)
        return self -- 返回自身以支持链式调用
    end

    -- 为obj添加其他方法
    obj.update_drive_static_info_by_sepecific_obj = function(self, nvme)
        static_info_updated = true
        lu.assertEquals(nvme, mock_nvme)
    end

    obj.update_asset_data_info = function(self)
        asset_info_updated = true
    end

    -- 执行测试
    c_drive.nvme_static_identified(obj, mock_nvme)

    -- 验证结果
    lu.assertTrue(task_created, "任务应该被创建")
    lu.assertTrue(task_loop_executed, "任务循环应该被执行")
    lu.assertTrue(static_info_updated, "静态信息应该被更新")
    lu.assertTrue(asset_info_updated, "资产信息应该被更新")
    lu.assertTrue(timeout_set_correctly, "超时时间应该设置为120000毫秒")
end

function TEST_Drive_Object:test_nvme_static_identified_with_identify_pd_true()
    -- 测试用例2：nvme对象存在但identify_pd为true的情况（应该提前返回）
    local task_created = false
    local static_info_updated = false
    local asset_info_updated = false

    local mock_nvme = {
        slot = 1,
        model = "Test NVMe"
    }

    local task_obj = {}
    local obj = {
        ObjectName = "TestDrive",
        identify_pd = true, -- 设置为true，应该提前返回
        new_task = function(self, task_name)
            task_created = true
            return task_obj
        end
    }

    -- 为task_obj添加loop方法
    task_obj.loop = function(self, callback)
        -- 执行回调函数测试内部逻辑
        callback()
        return self -- 返回自身以支持链式调用
    end

    -- 为task_obj添加set_timeout_ms方法
    task_obj.set_timeout_ms = function(self, timeout)
        return self -- 返回自身以支持链式调用
    end

    -- 为obj添加其他方法
    obj.update_drive_static_info_by_sepecific_obj = function(self, nvme)
        static_info_updated = true
    end

    obj.update_asset_data_info = function(self)
        asset_info_updated = true
    end

    -- 执行测试
    c_drive.nvme_static_identified(obj, mock_nvme)

    -- 验证结果
    lu.assertTrue(task_created, "任务应该被创建")
    lu.assertFalse(static_info_updated, "identify_pd为true时，静态信息不应该被更新")
    lu.assertFalse(asset_info_updated, "identify_pd为true时，资产信息不应该被更新")
end

function TEST_Drive_Object:test_nvme_static_identified_with_nil_nvme()
    -- 测试用例3：nvme对象为nil的情况（应该停止任务）
    local stop_task_called = false
    local stopped_task_name = nil

    local obj = {
        ObjectName = "TestDrive",
        stop_task = function(self, task_name)
            stop_task_called = true
            stopped_task_name = task_name
        end
    }

    -- 执行测试
    c_drive.nvme_static_identified(obj, nil)

    -- 验证结果
    lu.assertTrue(stop_task_called, "应该调用stop_task")
    lu.assertEquals(stopped_task_name[1], 'update_nvme_static')
    lu.assertEquals(stopped_task_name[2], "TestDrive")
end

function TEST_Drive_Object:test_nvme_static_identified_edge_cases()
    -- 测试用例4：边界情况测试
    local function_calls = {}

    local task_obj = {}
    local obj = {
        ObjectName = "",   -- 空字符串测试
        identify_pd = nil, -- nil值测试
        new_task = function(self, task_name)
            table.insert(function_calls, "new_task")
            return task_obj
        end
    }

    -- 为task_obj添加loop方法
    task_obj.loop = function(self, callback)
        table.insert(function_calls, "loop")
        callback()
        return self -- 返回自身以支持链式调用
    end

    -- 为task_obj添加set_timeout_ms方法
    task_obj.set_timeout_ms = function(self, timeout)
        table.insert(function_calls, "set_timeout_ms")
        return self -- 返回自身以支持链式调用
    end

    -- 为obj添加其他方法
    obj.update_drive_static_info_by_sepecific_obj = function(self, nvme)
        table.insert(function_calls, "update_drive_static_info_by_sepecific_obj")
    end

    obj.update_asset_data_info = function(self)
        table.insert(function_calls, "update_asset_data_info")
    end

    local mock_nvme = {}

    -- 执行测试
    c_drive.nvme_static_identified(obj, mock_nvme)

    -- 验证调用顺序
    local expected_calls = { "new_task", "loop", "update_drive_static_info_by_sepecific_obj", "update_asset_data_info",
        "set_timeout_ms" }
    lu.assertEquals(function_calls, expected_calls)
end

function TEST_Drive_Object:test_nvme_static_identified_task_name_generation()
    -- 测试用例5：测试任务名称生成的正确性
    local captured_task_names = {}

    local task_obj = {}
    local obj = {
        ObjectName = "Drive_Slot_5",
        identify_pd = false,
        new_task = function(self, task_name)
            table.insert(captured_task_names, { task_name[1], task_name[2] })
            return task_obj
        end
    }

    -- 为task_obj添加loop方法
    task_obj.loop = function(self, callback)
        callback()
        return self -- 返回自身以支持链式调用
    end

    -- 为task_obj添加set_timeout_ms方法
    task_obj.set_timeout_ms = function(self, timeout)
        return self -- 返回自身以支持链式调用
    end

    -- 为obj添加其他方法
    obj.update_drive_static_info_by_sepecific_obj = function(self, nvme) end
    obj.update_asset_data_info = function(self) end

    local mock_nvme = { model = "Samsung NVMe" }

    -- 执行测试
    c_drive.nvme_static_identified(obj, mock_nvme)

    -- 验证任务名称
    lu.assertEquals(#captured_task_names, 1)
    lu.assertEquals(captured_task_names[1][1], 'update_nvme_static')
    lu.assertEquals(captured_task_names[1][2], "Drive_Slot_5")
end

function TEST_Drive_Object:test_update_static_drive_info()
    local obj = {
        model = "Test Model",
        manufacturer = "Test Manufacturer",
        firmware_version = "1.0.0",
        interface_type = "NVMe",
        media_type = "SSD",
        serial_num = "123456789",
        form_factor = "2.5 inch"
    }

    drive = {}

    c_drive.update_static_drive_info(drive, obj)

    lu.assertEquals(drive.Model, "Test Model")
    lu.assertEquals(drive.Manufacturer, "Test Manufacturer")
    lu.assertEquals(drive.Revision, "1.0.0")
    lu.assertEquals(drive.Protocol, "NVMe")
    lu.assertEquals(drive.MediaType, "SSD")
    lu.assertEquals(drive.SerialNumber, "123456789")
    lu.assertEquals(drive.FormFactor, "2.5 inch")
end

-- 测试update_nvme_systemid函数 - nvme_configs为空的情况
-- 测试目的：验证当config_manager的nvme_configs为空时，函数应该提前返回，不设置system_id
-- 前置条件：config_manager.get_instance().nvme_configs为空表
-- 测试步骤：调用update_nvme_systemid函数
-- 预期结果：nvme.system_id应该为nil，函数提前返回
function TEST_Drive_Object:test_update_nvme_systemid_empty_configs()
    local config_manager = require 'config_manager'
    local original_get_instance = config_manager.get_instance
    
    -- Mock config_manager实例，设置nvme_configs为空表
    local mock_instance = {
        nvme_configs = {}
    }
    config_manager.get_instance = function()
        return mock_instance
    end

    -- 准备测试数据
    local drive_obj = {
        Id = 1,
        board_path = '',
        ObjectIdentifier = {1, 2, 3, 'test_segment'}
    }
    local nvme = {
        Slot = 1
    }

    -- 执行测试
    c_drive.update_nvme_systemid(drive_obj, nvme)

    -- 验证结果：由于nvme_configs为空，函数应该提前返回，system_id应该为nil
    lu.assertNil(nvme.system_id)

    -- 恢复原始函数
    config_manager.get_instance = original_get_instance
end

-- 测试update_nvme_systemid函数 - board_path为空，需要获取board_obj的完整流程
-- 测试目的：验证当drive_obj的board_path为空时，函数能够通过get_board_obj_prop获取board_path，
--           并成功调用mdb.get_object和config_manager.get_nvme_systemid来设置system_id
-- 前置条件：config_manager的nvme_configs不为空，drive_obj.board_path为空字符串
-- 测试步骤：
--   1. 调用get_board_obj_prop获取board对象信息
--   2. 设置drive_obj.board_path
--   3. 调用mdb.get_object获取backplane对象
--   4. 调用config_manager.get_nvme_systemid获取system_id
-- 预期结果：drive_obj.board_path应该被设置为'/test/path'，nvme.system_id应该被设置为100
function TEST_Drive_Object:test_update_nvme_systemid_get_board_path()
    local config_manager = require 'config_manager'
    local mdb = require 'mc.mdb'
    local object_manage = require 'mc.orm.object_manage'
    local client = require 'storage.client'

    -- 保存原始函数引用，用于测试后恢复
    local original_get_instance_cm = config_manager.get_instance
    local original_get_instance_om = object_manage.get_instance
    local original_get_object = mdb.get_object
    local original_get_board_objects = client.GetBoardObjects

    -- Mock config_manager实例，包含nvme_configs和get_nvme_systemid方法
    local mock_config_instance = {
        nvme_configs = {
            {MultiHostMappings = {}}
        },
        get_nvme_systemid = function(self, uid, slot_id)
            -- 验证参数正确性
            lu.assertEquals(uid, 'test_uid')
            lu.assertEquals(slot_id, 1)
            return 100
        end
    }
    config_manager.get_instance = function()
        return mock_config_instance
    end

    -- Mock object_manage实例，提供bus对象
    local mock_om_instance = {
        bus = 'test_bus'
    }
    object_manage.get_instance = function()
        return mock_om_instance
    end

    -- Mock mdb.get_object，验证调用参数并返回backplane对象
    local mock_board_obj = {
        UID = 'test_uid',
        path = '/test/path'
    }
    mdb.get_object = function(bus, path, interface)
        -- 验证mdb.get_object的调用参数
        lu.assertEquals(bus, 'test_bus')
        lu.assertEquals(path, '/test/path')
        lu.assertEquals(interface, 'bmc.kepler.Systems.Board.Unit')
        return mock_board_obj
    end

    -- Mock client.GetBoardObjects，返回匹配的board对象
    -- 注意：get_board_obj_prop使用string.match(path, '.*_(.+)')提取路径最后一个下划线后的段
    -- 对于路径'/test/path_test_segment'，string.match会提取出'test_segment'
    -- 需要与drive_obj.ObjectIdentifier[4]匹配
    -- 路径格式：最后一个下划线后的部分应该等于ObjectIdentifier[4]
    -- 例如：路径'/test/path_test_segment'匹配ObjectIdentifier[4]='test_segment'
    local mock_board_objects = {
        ['/test/path_test_segment'] = {
            Position = 'test_position',
            NodeId = 'test_node',
            SilkText = 'test_silk',
            path = '/test/path'  -- 这个path会被get_board_obj_prop提取并设置到drive_obj.board_path
        }
    }
    -- Mock GetBoardObjects方法，支持冒号调用（client:GetBoardObjects()）
    -- 冒号调用会自动传递self作为第一个参数，但这里我们忽略self参数
    -- client是一个实例对象，GetBoardObjects是它的方法
    client.GetBoardObjects = function(self)
        return mock_board_objects
    end

    -- 准备测试数据：drive_obj的board_path为空，需要通过get_board_obj_prop获取
    -- ObjectIdentifier[4] = 'test_segment' 用于匹配board对象的路径
    -- get_board_obj_prop会从路径中提取最后一个下划线后的段进行匹配
    -- string.match('/test/path_test_segment', '.*_(.+)') 会返回 'test_segment'
    local drive_obj = {
        Id = 1,
        board_path = '',
        ObjectIdentifier = {1, 2, 3, 'segment'}  -- 用于匹配board对象路径中的最后一个段
    }
    local nvme = {
        Slot = 1
    }

    -- 执行测试
    c_drive.update_nvme_systemid(drive_obj, nvme)

    -- 验证结果
    -- 1. board_path应该被正确设置（从board对象的path字段获取）
    lu.assertEquals(drive_obj.board_path, '/test/path')
    -- 2. system_id应该被正确设置（通过config_manager.get_nvme_systemid获取）
    lu.assertEquals(nvme.system_id, 100)

    -- 恢复原始函数
    config_manager.get_instance = original_get_instance_cm
    object_manage.get_instance = original_get_instance_om
    mdb.get_object = original_get_object
    client.GetBoardObjects = original_get_board_objects
end

-- 测试update_nvme_systemid函数 - board_path已存在的情况
-- 测试目的：验证当drive_obj的board_path已经存在时，函数应该直接使用该path，
--           跳过get_board_obj_prop的调用，直接调用mdb.get_object获取backplane对象
-- 前置条件：drive_obj.board_path已设置为'/existing/path'
-- 测试步骤：
--   1. 跳过get_board_obj_prop调用（因为board_path已存在）
--   2. 直接使用现有的board_path调用mdb.get_object
--   3. 调用config_manager.get_nvme_systemid获取system_id
-- 预期结果：nvme.system_id应该被设置为200，board_path保持不变
function TEST_Drive_Object:test_update_nvme_systemid_existing_board_path()
    local config_manager = require 'config_manager'
    local mdb = require 'mc.mdb'
    local object_manage = require 'mc.orm.object_manage'

    -- 保存原始函数引用
    local original_get_instance_cm = config_manager.get_instance
    local original_get_instance_om = object_manage.get_instance
    local original_get_object = mdb.get_object

    -- Mock config_manager实例
    local mock_config_instance = {
        nvme_configs = {
            {MultiHostMappings = {}}
        },
        get_nvme_systemid = function(self, uid, slot_id)
            -- 验证get_nvme_systemid的调用参数
            lu.assertEquals(uid, 'test_uid')
            lu.assertEquals(slot_id, 2)
            return 200
        end
    }
    config_manager.get_instance = function()
        return mock_config_instance
    end

    -- Mock object_manage实例
    local mock_om_instance = {
        bus = 'test_bus'
    }
    object_manage.get_instance = function()
        return mock_om_instance
    end

    -- Mock mdb.get_object，验证使用已存在的board_path
    local mock_board_obj = {
        UID = 'test_uid',
        path = '/test/path'
    }
    mdb.get_object = function(bus, path, interface)
        -- 验证使用的是已存在的board_path，而不是通过get_board_obj_prop获取的
        lu.assertEquals(bus, 'test_bus')
        lu.assertEquals(path, '/existing/path')
        return mock_board_obj
    end

    -- 准备测试数据：board_path已存在
    local drive_obj = {
        Id = 1,
        board_path = '/existing/path',  -- board_path已设置，不需要通过get_board_obj_prop获取
        ObjectIdentifier = {1, 2, 3, 'test_segment'}
    }
    local nvme = {
        Slot = 2
    }

    -- 执行测试
    c_drive.update_nvme_systemid(drive_obj, nvme)

    -- 验证结果：system_id应该被正确设置
    lu.assertEquals(nvme.system_id, 200)

    -- 恢复原始函数
    config_manager.get_instance = original_get_instance_cm
    object_manage.get_instance = original_get_instance_om
    mdb.get_object = original_get_object
end

-- 测试update_nvme_systemid函数 - get_board_obj_prop返回空对象的情况
-- 测试目的：验证当client.GetBoardObjects返回nil时，get_board_obj_prop返回空对象，
--           函数应该无法获取board_path，因此不会设置system_id
-- 前置条件：client.GetBoardObjects返回nil
-- 测试步骤：
--   1. 调用get_board_obj_prop，由于GetBoardObjects返回nil，返回空对象
--   2. board_path保持为空字符串
--   3. 由于board_path为空，不会调用mdb.get_object
-- 预期结果：drive_obj.board_path应该保持为空字符串，nvme.system_id应该为nil
function TEST_Drive_Object:test_update_nvme_systemid_empty_board_obj()
    local config_manager = require 'config_manager'
    local client = require 'storage.client'

    -- 保存原始函数引用
    local original_get_instance = config_manager.get_instance
    local original_get_board_objects = client.GetBoardObjects

    -- Mock config_manager实例
    local mock_instance = {
        nvme_configs = {
            {MultiHostMappings = {}}
        }
    }
    config_manager.get_instance = function()
        return mock_instance
    end

    -- Mock client.GetBoardObjects返回nil，模拟无法获取board对象的情况
    client.GetBoardObjects = function(self)
        return nil
    end

    -- 准备测试数据
    local drive_obj = {
        Id = 1,
        board_path = '',
        ObjectIdentifier = {1, 2, 3, 'test_segment'}
    }
    local nvme = {
        Slot = 1
    }

    -- 执行测试
    c_drive.update_nvme_systemid(drive_obj, nvme)

    -- 验证结果
    -- 1. board_path应该保持为空，因为GetBoardObjects返回nil
    lu.assertEquals(drive_obj.board_path, '')
    -- 2. system_id应该为nil，因为无法获取board_path
    lu.assertNil(nvme.system_id)

    -- 恢复原始函数
    config_manager.get_instance = original_get_instance
    client.GetBoardObjects = original_get_board_objects
end

-- 测试update_nvme_systemid函数 - get_board_obj_prop返回的board_obj没有path字段的情况
-- 测试目的：验证当GetBoardObjects返回的board对象没有path字段时，
--           函数应该无法设置board_path，因此不会设置system_id
-- 前置条件：GetBoardObjects返回的board对象缺少path字段
-- 测试步骤：
--   1. 调用get_board_obj_prop获取board对象
--   2. board对象没有path字段，board_path保持为空字符串
--   3. 由于board_path为空，不会调用mdb.get_object
-- 预期结果：drive_obj.board_path应该保持为空字符串，nvme.system_id应该为nil
function TEST_Drive_Object:test_update_nvme_systemid_board_obj_no_path()
    local config_manager = require 'config_manager'
    local client = require 'storage.client'

    -- 保存原始函数引用
    local original_get_instance = config_manager.get_instance
    local original_get_board_objects = client.GetBoardObjects

    -- Mock config_manager实例
    local mock_instance = {
        nvme_configs = {
            {MultiHostMappings = {}}
        }
    }
    config_manager.get_instance = function()
        return mock_instance
    end

    -- Mock client.GetBoardObjects返回的board对象缺少path字段
    local mock_board_objects = {
        ['/test/path_test_segment'] = {
            Position = 'test_position',
            NodeId = 'test_node',
            SilkText = 'test_silk'
            -- 注意：没有 path 字段，模拟异常情况
        }
    }
    client.GetBoardObjects = function(self)
        return mock_board_objects
    end

    -- 准备测试数据
    local drive_obj = {
        Id = 1,
        board_path = '',
        ObjectIdentifier = {1, 2, 3, 'test_segment'}
    }
    local nvme = {
        Slot = 1
    }

    -- 执行测试
    c_drive.update_nvme_systemid(drive_obj, nvme)

    -- 验证结果
    -- 1. board_path应该保持为空，因为board对象没有path字段
    lu.assertEquals(drive_obj.board_path, '')
    -- 2. system_id应该为nil，因为无法获取有效的board_path
    lu.assertNil(nvme.system_id)

    -- 恢复原始函数
    config_manager.get_instance = original_get_instance
    client.GetBoardObjects = original_get_board_objects
end

-- 测试update_nvme_systemid函数 - mdb.get_object调用失败的情况
-- 测试目的：验证当mdb.get_object抛出异常时，函数应该捕获异常并记录错误日志，
--           不会设置system_id，函数提前返回
-- 前置条件：mdb.get_object抛出异常
-- 测试步骤：
--   1. 获取board_path
--   2. 调用mdb.get_object时抛出异常
--   3. pcall捕获异常，记录错误日志
--   4. 函数提前返回
-- 预期结果：应该记录错误日志，nvme.system_id应该为nil
function TEST_Drive_Object:test_update_nvme_systemid_mdb_get_object_failed()
    local config_manager = require 'config_manager'
    local mdb = require 'mc.mdb'
    local object_manage = require 'mc.orm.object_manage'
    local client = require 'storage.client'

    -- 保存原始函数引用
    local original_get_instance_cm = config_manager.get_instance
    local original_get_instance_om = object_manage.get_instance
    local original_get_object = mdb.get_object
    local original_get_board_objects = client.GetBoardObjects

    -- Mock config_manager实例
    local mock_config_instance = {
        nvme_configs = {
            {MultiHostMappings = {}}
        }
    }
    config_manager.get_instance = function()
        return mock_config_instance
    end

    -- Mock object_manage实例
    local mock_om_instance = {
        bus = 'test_bus'
    }
    object_manage.get_instance = function()
        return mock_om_instance
    end

    -- Mock mdb.get_object抛出异常，模拟调用失败的情况
    mdb.get_object = function(bus, path, interface)
        error('mdb.get_object failed')
    end

    -- Mock client.GetBoardObjects返回有效的board对象
    local mock_board_objects = {
        ['/test/path_test_segment'] = {
            Position = 'test_position',
            NodeId = 'test_node',
            SilkText = 'test_silk',
            path = '/test/path'
        }
    }
    client.GetBoardObjects = function(self)
        return mock_board_objects
    end

    -- 准备测试数据
    local drive_obj = {
        Id = 1,
        board_path = '',
        ObjectIdentifier = {1, 2, 3, 'test_segment'}
    }
    local nvme = {
        Slot = 1
    }

    -- 执行测试
    c_drive.update_nvme_systemid(drive_obj, nvme)

    -- 验证结果：system_id应该为nil，因为mdb.get_object失败
    lu.assertNil(nvme.system_id)

    -- 恢复原始函数
    config_manager.get_instance = original_get_instance_cm
    object_manage.get_instance = original_get_instance_om
    mdb.get_object = original_get_object
    client.GetBoardObjects = original_get_board_objects
end

-- 测试update_nvme_systemid函数 - get_nvme_systemid返回nil的情况
-- 测试目的：验证当config_manager.get_nvme_systemid返回nil时（找不到匹配的配置），
--           函数应该将nvme.system_id设置为nil
-- 前置条件：所有前置步骤成功（获取board_path、mdb.get_object成功），但get_nvme_systemid返回nil
-- 测试步骤：
--   1. 获取board_path成功
--   2. 调用mdb.get_object成功，获取backplane对象
--   3. 调用config_manager.get_nvme_systemid返回nil（找不到匹配的配置）
-- 预期结果：nvme.system_id应该被设置为nil
function TEST_Drive_Object:test_update_nvme_systemid_get_systemid_nil()
    local config_manager = require 'config_manager'
    local mdb = require 'mc.mdb'
    local object_manage = require 'mc.orm.object_manage'
    local client = require 'storage.client'

    -- 保存原始函数引用
    local original_get_instance_cm = config_manager.get_instance
    local original_get_instance_om = object_manage.get_instance
    local original_get_object = mdb.get_object
    local original_get_board_objects = client.GetBoardObjects

    -- Mock config_manager实例，get_nvme_systemid返回nil，模拟找不到匹配配置的情况
    local mock_config_instance = {
        nvme_configs = {
            {MultiHostMappings = {}}
        },
        get_nvme_systemid = function(self, uid, slot_id)
            -- 返回nil，模拟找不到匹配的system_id配置
            return nil
        end
    }
    config_manager.get_instance = function()
        return mock_config_instance
    end

    -- Mock object_manage实例
    local mock_om_instance = {
        bus = 'test_bus'
    }
    object_manage.get_instance = function()
        return mock_om_instance
    end

    -- Mock mdb.get_object成功返回backplane对象
    local mock_board_obj = {
        UID = 'test_uid',
        path = '/test/path'
    }
    mdb.get_object = function(bus, path, interface)
        return mock_board_obj
    end

    -- Mock client.GetBoardObjects返回有效的board对象
    local mock_board_objects = {
        ['/test/path_test_segment'] = {
            Position = 'test_position',
            NodeId = 'test_node',
            SilkText = 'test_silk',
            path = '/test/path'
        }
    }
    client.GetBoardObjects = function(self)
        return mock_board_objects
    end

    -- 准备测试数据
    local drive_obj = {
        Id = 1,
        board_path = '',
        ObjectIdentifier = {1, 2, 3, 'test_segment'}
    }
    local nvme = {
        Slot = 1
    }

    -- 执行测试
    c_drive.update_nvme_systemid(drive_obj, nvme)

    -- 验证结果：system_id应该为nil，因为get_nvme_systemid返回nil
    lu.assertNil(nvme.system_id)

    -- 恢复原始函数
    config_manager.get_instance = original_get_instance_cm
    object_manage.get_instance = original_get_instance_om
    mdb.get_object = original_get_object
    client.GetBoardObjects = original_get_board_objects
end

function TEST_Drive_Object:test_process_when_nvme_removed()
    local ret
    local obj = {
        FaultLed = 1,
        LinkFault = true,
        stop_task = function(...) return {
            loop = function(obj, cb)
                cb(1)
                return {set_timeout_ms = function(...) return end}
            end
        } end,
        set_default_values = function()
        end,
        set_presence = function()
        end,
        set_fault_led_by_smc = function()
        end,
        set_link_fault = function()
            ret = true
        end
    }
    c_drive.process_when_nvme_removed(obj)
    lu.assertEquals(ret, true)
end


function TEST_Drive_Object:test_check_missing()
    local drive_obj = {
        Missing = 0,
        EnclosureId = 1,
        SlotNumber = 2
    }
    local pd_list = {
        {
            enclosure_id = 1,
            slot_num = 2
        }
    }
    c_drive.check_missing(drive_obj, pd_list)
    lu.assertEquals(drive_obj.missing_count, 0)
    drive_obj.SlotNumber = 3
    c_drive.check_missing(drive_obj, pd_list)
    lu.assertEquals(drive_obj.Missing, 0)
    drive_obj.missing_count = 5
    c_drive.check_missing(drive_obj, pd_list)
    lu.assertEquals(drive_obj.Missing, 2)
end