-- Copyright (c) 2026 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'

-- 定义 mock 对象（但不设置到 package.loaded，避免文件加载时污染全局环境）
local mock_skynet = {
    fork_once = function(func)
        func() -- Execute immediately for testing
    end,
    fork = function(func)
        func() -- Execute immediately for testing
    end,
    sleep = function(ms) end
}

-- mock_context 不再在文件顶层定义，改为在 setUp 中动态创建

local client_calls = {}
local client_callbacks = {}  -- 用于存储回调函数

local mock_client = {
    UpdateServiceUpdateServicePrepareReply = function(self, ctx, system_id, firmware_type, version, ret_code, parameters)
        table.insert(client_calls, {
            method = 'PrepareReply',
            system_id = system_id,
            firmware_type = firmware_type,
            version = version,
            ret_code = ret_code,
            parameters = parameters
        })
    end,
    UpdateServiceUpdateServiceProcessReply = function(self, ctx, system_id, firmware_type, ret_code, parameters)
        table.insert(client_calls, {
            method = 'ProcessReply',
            system_id = system_id,
            firmware_type = firmware_type,
            ret_code = ret_code,
            parameters = parameters
        })
    end,
    UpdateServiceUpdateServiceFinishReply = function(self, ctx, system_id, firmware_type, ret_code, parameters)
        table.insert(client_calls, {
            method = 'FinishReply',
            system_id = system_id,
            firmware_type = firmware_type,
            ret_code = ret_code,
            parameters = parameters
        })
    end,
    UpdateServiceUpdateServiceUpdateUpgradeStatus = function(self, ctx, system_id, firmware_type, code, progress, status, parameters)
        table.insert(client_calls, {
            method = 'UpdateUpgradeStatus',
            system_id = system_id,
            firmware_type = firmware_type,
            code = code,
            progress = progress,
            status = status,
            parameters = parameters
        })
    end,
    PFileFileChown = function(self, ctx, nil_arg, path, uid, gid)
        table.insert(client_calls, {
            method = 'FileChown',
            path = path,
            uid = uid,
            gid = gid
        })
        return true, nil
    end,
    FirmwareActiveFirmwareActiveActiveProcessReply = function(self, ctx, system_id, firmware_type, ret_code, parameters)
        table.insert(client_calls, {
            method = 'ActiveProcessReply',
            system_id = system_id,
            firmware_type = firmware_type,
            ret_code = ret_code,
            parameters = parameters
        })
    end,
    SubscribeUpdateServiceUpdateServiceUpgradePrepareSignal = function(callback)
        client_callbacks.on_prepare = callback
    end,
    SubscribeUpdateServiceUpdateServiceUpgradeProcessSignal = function(callback)
        client_callbacks.on_process = callback
    end,
    SubscribeUpdateServiceUpdateServiceUpgradeFinishSignal = function(callback)
        client_callbacks.on_finish = callback
    end,
    SubscribeFirmwareActiveFirmwareActiveActiveProcessSignal = function(callback)
        client_callbacks.on_active = callback
    end
}

local mock_network_adapter_firmware_objects = {}
local mock_network_adapter_firmware = {
    collection = {
        objects = mock_network_adapter_firmware_objects,
        count = 0,
        fold = function(self, func, acc)
            for key, obj in pairs(self.objects) do
                local result = func(acc, obj, key)
                if result ~= nil then
                    return result
                end
            end
            return acc
        end
    }
}

local mock_fructl = {
    get_power_status = function()
        return 'OFF'  -- 默认下电状态，这样会执行更多代码路径
    end,
    set_poweron_lock_until_success = function(bus, sys_id, state, time, reason)
        return true
    end
}

local mock_vos = {
    get_file_accessible = function(path)
        if path:match('not_exist') or path:match('/data/backup/nic/up_cfg/') then
            return false
        end
        return true
    end
}

local mock_utils = {
    remove_file = function(path)
        return true
    end,
    copy_file = function(src, dst)
        return true
    end,
    secure_tar_unzip = function(src, dst, max_size, max_files)
        return true
    end,
    safe_close_file = function(fd, callback)
        if callback then callback() end
    end
}

local mock_utils_core = {
    dir = function(path)
        if path:match('/data/backup/nic/up_cfg/') then
            return {}
        end
        return {'Firmware1', 'other.txt'}
    end,
    stat = function(path)
        return {st_size = 1024}
    end
}

-- Mock upgrade_process 和 active_process（需要在 setUp 中根据 upgrade_defs 创建）
local mock_upgrade_process
local mock_active_process

-- 延迟加载被测试模块，在 setUp 中加载
local upgrade_defs
local network_adapter_upgrade

TEST_Network_Adapter_Upgrade = {}

function TEST_Network_Adapter_Upgrade:setUp()
    -- 设置 package.loaded 中的 mock（只在测试用例执行时设置，避免文件加载时污染全局环境）
    package.loaded['skynet'] = mock_skynet
    package.loaded['mc.logging'] = {
        notice = function() end,
        error = function() end,
        info = function() end,
        maintenance = function() end,
        running = function() end,
        MLOG_INFO = 0,
        RLOG_INFO = 0,
        RLOG_ERROR = 1,
        FC__PUBLIC_OK = 0
    }
    -- 对于 mc.context，先加载真实模块，然后只覆盖需要 mock 的函数，保留其他函数（如 get_context）
    package.loaded['mc.context'] = nil
    local real_context = require 'mc.context'
    local context_mock = {}
    -- 复制真实模块的所有函数
    for k, v in pairs(real_context) do
        context_mock[k] = v
    end
    -- 覆盖需要 mock 的函数
    context_mock.new = function()
        return {}
    end
    package.loaded['mc.context'] = context_mock
    
    package.loaded['network_adapter.client'] = mock_client
    package.loaded['upgrade.network_adapter_firmware_object'] = mock_network_adapter_firmware
    package.loaded['infrastructure.fructl'] = mock_fructl
    
    -- 对于 utils.vos，先加载真实模块，然后只覆盖需要 mock 的函数，保留其他函数（如 vos_tick_get）
    package.loaded['utils.vos'] = nil
    local real_vos = require 'utils.vos'
    local vos_mock = {}
    -- 复制真实模块的所有函数
    for k, v in pairs(real_vos) do
        vos_mock[k] = v
    end
    -- 覆盖需要 mock 的函数
    vos_mock.get_file_accessible = function(path)
        if path:match('not_exist') or path:match('/data/backup/nic/up_cfg/') then
            return false
        end
        return true
    end
    package.loaded['utils.vos'] = vos_mock
    
    package.loaded['mc.utils'] = mock_utils
    package.loaded['utils.core'] = mock_utils_core
    
    -- 先加载 upgrade_defs，因为 mock_upgrade_process 和 mock_active_process 需要它
    package.loaded['upgrade.upgrade_defs'] = nil
    upgrade_defs = require 'upgrade.upgrade_defs'
    
    -- Mock upgrade_process（需要 upgrade_defs）
    mock_upgrade_process = {
        initial_set_route = function()
            return true
        end,
        network_adapter_upgrade_prepare = function(self, system_id, cfg_path, hpm_path)
            self.is_network_adapter_upgrading = true
            self.hpm_path = hpm_path
            self.before_upgrade_version = '1.0.0'
            if not next(self.cfgs or {}) then
                self.cfgs = {Firmware1 = {name = 'Firmware1', component_id = 1, component_idex = 2}}
            end
            return upgrade_defs.RET.OK, '1.0.0'
        end,
        network_adapter_upgrade_process = function(self, system_id, firmware_type, file_path, parameters)
            return upgrade_defs.RET.OK
        end,
        network_adapter_upgrade_finish = function(self)
            return upgrade_defs.RET.OK
        end
    }
    package.loaded['upgrade.upgrade_process'] = mock_upgrade_process
    
    -- Mock active_process（需要 upgrade_defs）
    mock_active_process = {
        network_adapter_active_process = function(self)
            return upgrade_defs.RET.OK
        end
    }
    package.loaded['upgrade.active_process'] = mock_active_process
    
    package.loaded['mc.singleton'] = function(cls)
        return cls
    end
    
    -- 清除被测试模块的缓存，确保使用最新的 mock
    package.loaded['upgrade.network_adapter_upgrade'] = nil
    
    -- 加载被测试模块（使用最新的 mock）
    network_adapter_upgrade = require 'upgrade.network_adapter_upgrade'
    
    -- Reset client calls
    client_calls = {}
    
    -- Reset mock data
    for k in pairs(mock_network_adapter_firmware_objects) do
        mock_network_adapter_firmware_objects[k] = nil
    end
    mock_network_adapter_firmware.collection.objects = mock_network_adapter_firmware_objects
    mock_network_adapter_firmware.collection.count = 0
    
    -- Reset fructl mock
    mock_fructl.get_power_status = function()
        return 'PowerOn'
    end
    
    -- Reset mock functions to default behavior
    mock_fructl.get_power_status = function()
        return 'PowerOn'
    end
    
    mock_upgrade_process.network_adapter_upgrade_prepare = function(self, system_id, cfg_path, hpm_path)
        self.is_network_adapter_upgrading = true
        self.hpm_path = hpm_path
        self.before_upgrade_version = '1.0.0'
        if not next(self.cfgs or {}) then
            self.cfgs = {Firmware1 = {name = 'Firmware1', component_id = 1, component_idex = 2}}
        end
        return upgrade_defs.RET.OK, '1.0.0'
    end
    
    mock_upgrade_process.network_adapter_upgrade_process = function(self, system_id, firmware_type, file_path, parameters)
        return upgrade_defs.RET.OK
    end
    
    mock_upgrade_process.network_adapter_upgrade_finish = function(self)
        return upgrade_defs.RET.OK
    end
    
    -- Get a fresh instance
    self.upgrade_instance = network_adapter_upgrade
    self.upgrade_instance.cfgs = {}
    self.upgrade_instance.upgrade_list = {}
    self.upgrade_instance.before_upgrade_version = ''
    self.upgrade_instance.is_network_adapter_upgrading = false
    self.upgrade_instance.is_network_adapter_activing = false
    self.upgrade_instance.hpm_path = ""
    self.upgrade_instance.power_state = nil
    self.upgrade_instance.poweron_locked = false
    self.upgrade_instance.system_id = 1
    self.upgrade_instance.bus = {}
end

function TEST_Network_Adapter_Upgrade:tearDown()
    -- 重置调用记录
    client_calls = {}
    
    -- 只清除 test_upgrade 特有的模块，不清除基础模块（如 skynet、mc.logging 等）
    -- 基础模块可能被其他测试使用，清除它们会导致其他测试失败
    package.loaded['upgrade.network_adapter_firmware_object'] = nil
    package.loaded['upgrade.upgrade_process'] = nil
    package.loaded['upgrade.active_process'] = nil
    package.loaded['upgrade.upgrade_defs'] = nil
    package.loaded['upgrade.network_adapter_upgrade'] = nil
end

-- 测试初始化
function TEST_Network_Adapter_Upgrade:test_init()
    local instance = network_adapter_upgrade
    instance:init({})
    
    lu.assertNotNil(instance.cfgs)
    lu.assertEquals(#instance.cfgs, 0)
    lu.assertNotNil(instance.upgrade_list)
    lu.assertEquals(#instance.upgrade_list, 0)
    lu.assertEquals(instance.before_upgrade_version, '')
    lu.assertEquals(instance.is_network_adapter_upgrading, false)
    lu.assertEquals(instance.is_network_adapter_activing, false)
end

-- 测试on_upgrade_prepare - 非Nic类型固件
function TEST_Network_Adapter_Upgrade:test_on_upgrade_prepare_not_nic_firmware()
    mock_network_adapter_firmware.collection.count = 1
    mock_network_adapter_firmware_objects['test'] = {
        ComponentID = 1,
        ComponentIDEx = 2,
        FirmwareVersion = '1.0.0'
    }
    
    self.upgrade_instance:on_upgrade_prepare(
        {},
        1,
        'Bmc', -- 不是Nic类型
        '/tmp/test.cfg',
        '/tmp/test.hpm',
        {}
    )
    
    -- 不应该有任何client调用
    lu.assertEquals(#client_calls, 0)
end

-- 测试on_upgrade_prepare - 没有network adapter firmware对象
function TEST_Network_Adapter_Upgrade:test_on_upgrade_prepare_no_network_adapter_firmware()
    mock_network_adapter_firmware.collection.count = 0
    mock_network_adapter_firmware.collection.objects = {}
    
    self.upgrade_instance:on_upgrade_prepare(
        {},
        1,
        'Nic',
        '/tmp/test.cfg',
        '/tmp/test.hpm',
        {}
    )
    
    -- 应该返回错误
    lu.assertEquals(#client_calls, 1)
    lu.assertEquals(client_calls[1].method, 'PrepareReply')
    lu.assertEquals(client_calls[1].ret_code, upgrade_defs.RET.ERR)
end

-- 测试on_upgrade_prepare - 已经在升级中
function TEST_Network_Adapter_Upgrade:test_on_upgrade_prepare_already_upgrading()
    mock_network_adapter_firmware.collection.count = 1
    mock_network_adapter_firmware_objects['test'] = {
        ComponentID = 1,
        ComponentIDEx = 2,
        FirmwareVersion = '1.0.0'
    }
    self.upgrade_instance.is_network_adapter_upgrading = true
    
    self.upgrade_instance:on_upgrade_prepare(
        {},
        1,
        'Nic',
        '/tmp/test.cfg',
        '/tmp/test.hpm',
        {}
    )
    
    -- 应该返回IN_UPGRADING错误
    lu.assertEquals(#client_calls, 1)
    lu.assertEquals(client_calls[1].method, 'PrepareReply')
    lu.assertEquals(client_calls[1].ret_code, upgrade_defs.RET.IN_UPGRADING)
end

-- 测试on_upgrade_prepare - FileChown失败
function TEST_Network_Adapter_Upgrade:test_on_upgrade_prepare_chown_failed()
    mock_network_adapter_firmware.collection.count = 1
    mock_network_adapter_firmware_objects['test'] = {
        ComponentID = 1,
        ComponentIDEx = 2,
        FirmwareVersion = '1.0.0'
    }
    
    -- Mock FileChown失败
    local original_chown = mock_client.PFileFileChown
    mock_client.PFileFileChown = function(self, ctx, nil_arg, path, uid, gid)
        table.insert(client_calls, {
            method = 'FileChown',
            path = path,
            uid = uid,
            gid = gid
        })
        return false, 'permission denied'
    end
    
    self.upgrade_instance:on_upgrade_prepare(
        {},
        1,
        'Nic',
        '/tmp/test.cfg',
        '/tmp/test.hpm',
        {}
    )
    
    -- 应该返回错误
    lu.assertTrue(#client_calls >= 2) -- FileChown + PrepareReply
    lu.assertEquals(client_calls[1].method, 'FileChown')
    lu.assertEquals(client_calls[2].method, 'PrepareReply')
    lu.assertEquals(client_calls[2].ret_code, upgrade_defs.RET.ERR)
    
    -- 恢复原始函数
    mock_client.PFileFileChown = original_chown
end

-- 测试on_upgrade_prepare - 成功场景
function TEST_Network_Adapter_Upgrade:test_on_upgrade_prepare_success()
    mock_network_adapter_firmware.collection.count = 1
    mock_network_adapter_firmware_objects['test'] = {
        ComponentID = 1,
        ComponentIDEx = 2,
        FirmwareVersion = '1.0.0'
    }
    
    self.upgrade_instance:on_upgrade_prepare(
        {},
        1,
        'Nic',
        '/tmp/test.cfg',
        '/tmp/test.hpm',
        {}
    )
    
    -- 应该有FileChown和PrepareReply调用
    lu.assertTrue(#client_calls >= 2)
    
    -- 检查FileChown调用
    local has_file_chown = false
    for _, call in ipairs(client_calls) do
        if call.method == 'FileChown' then
            has_file_chown = true
            lu.assertEquals(call.uid, 104)
            lu.assertEquals(call.gid, 104)
        end
    end
    lu.assertTrue(has_file_chown)
    
    -- 检查PrepareReply
    local prepare_reply = nil
    for _, call in ipairs(client_calls) do
        if call.method == 'PrepareReply' then
            prepare_reply = call
            break
        end
    end
    lu.assertNotNil(prepare_reply)
    lu.assertEquals(prepare_reply.ret_code, upgrade_defs.RET.OK)
    lu.assertEquals(prepare_reply.firmware_type, 'Nic')
    lu.assertEquals(prepare_reply.version, '1.0.0')
end

-- 测试on_upgrade_prepare - upgrade_process抛出异常
function TEST_Network_Adapter_Upgrade:test_on_upgrade_prepare_process_exception()
    mock_network_adapter_firmware.collection.count = 1
    mock_network_adapter_firmware_objects['test'] = {
        ComponentID = 1,
        ComponentIDEx = 2,
        FirmwareVersion = '1.0.0'
    }
    
    -- Mock upgrade_process抛出异常
    local original_prepare = mock_upgrade_process.network_adapter_upgrade_prepare
    mock_upgrade_process.network_adapter_upgrade_prepare = function()
        error('prepare failed')
    end
    
    self.upgrade_instance:on_upgrade_prepare(
        {},
        1,
        'Nic',
        '/tmp/test.cfg',
        '/tmp/test.hpm',
        {}
    )
    
    -- 应该捕获异常并返回错误
    local prepare_reply = nil
    for _, call in ipairs(client_calls) do
        if call.method == 'PrepareReply' then
            prepare_reply = call
            break
        end
    end
    lu.assertNotNil(prepare_reply)
    lu.assertEquals(prepare_reply.ret_code, upgrade_defs.RET.ERR)
    lu.assertEquals(prepare_reply.version, '')
    
    -- 恢复原始函数
    mock_upgrade_process.network_adapter_upgrade_prepare = original_prepare
end

-- 测试on_upgrade_process - 非Nic类型固件
function TEST_Network_Adapter_Upgrade:test_on_upgrade_process_not_nic_firmware()
    self.upgrade_instance:on_upgrade_process(
        {},
        1,
        'Bmc',
        '/tmp/firmware.tar',
        {}
    )
    
    -- 不应该有任何client调用
    lu.assertEquals(#client_calls, 0)
end

-- 测试on_upgrade_process - 没有配置信息
function TEST_Network_Adapter_Upgrade:test_on_upgrade_process_no_cfgs()
    self.upgrade_instance.cfgs = {}
    
    self.upgrade_instance:on_upgrade_process(
        {},
        1,
        'Nic',
        '/tmp/firmware.tar',
        {}
    )
    
    -- 应该返回错误
    lu.assertTrue(#client_calls >= 1)
    local process_reply = nil
    for _, call in ipairs(client_calls) do
        if call.method == 'ProcessReply' then
            process_reply = call
            break
        end
    end
    lu.assertNotNil(process_reply)
    lu.assertEquals(process_reply.ret_code, upgrade_defs.RET.ERR)
    
    -- 资源应该被清理
    lu.assertEquals(self.upgrade_instance.is_network_adapter_upgrading, false)
end

-- 测试on_upgrade_process - 电源状态为nil
function TEST_Network_Adapter_Upgrade:test_on_upgrade_process_power_state_nil()
    self.upgrade_instance.cfgs = {Firmware1 = {}}
    
    -- Mock电源状态为nil
    local original_get_power = mock_fructl.get_power_status
    mock_fructl.get_power_status = function()
        return nil
    end
    
    self.upgrade_instance:on_upgrade_process(
        {},
        1,
        'Nic',
        '/tmp/firmware.tar',
        {}
    )
    
    -- 应该返回错误
    local process_reply = nil
    for _, call in ipairs(client_calls) do
        if call.method == 'ProcessReply' then
            process_reply = call
            break
        end
    end
    lu.assertNotNil(process_reply)
    lu.assertEquals(process_reply.ret_code, upgrade_defs.RET.ERR)
    
    -- 恢复原始函数
    mock_fructl.get_power_status = original_get_power
end

-- 测试on_upgrade_process - 成功场景
function TEST_Network_Adapter_Upgrade:test_on_upgrade_process_success()
    self.upgrade_instance.cfgs = {Firmware1 = {}}
    
    self.upgrade_instance:on_upgrade_process(
        {},
        1,
        'Nic',
        '/tmp/firmware.tar',
        {}
    )
    
    -- 应该有UpdateUpgradeStatus和ProcessReply调用
    lu.assertTrue(#client_calls >= 2)
    
    -- 检查UpdateUpgradeStatus调用
    local has_status_update = false
    for _, call in ipairs(client_calls) do
        if call.method == 'UpdateUpgradeStatus' then
            has_status_update = true
            lu.assertEquals(call.progress, 40)
            lu.assertEquals(call.status, 'Running')
        end
    end
    lu.assertTrue(has_status_update)
    
    -- 检查ProcessReply
    local process_reply = nil
    for _, call in ipairs(client_calls) do
        if call.method == 'ProcessReply' then
            process_reply = call
            break
        end
    end
    lu.assertNotNil(process_reply)
    lu.assertEquals(process_reply.ret_code, upgrade_defs.RET.OK)
    lu.assertEquals(process_reply.firmware_type, 'Nic')
end

-- 测试on_upgrade_process - upgrade_process返回错误
function TEST_Network_Adapter_Upgrade:test_on_upgrade_process_upgrade_failed()
    self.upgrade_instance.cfgs = {Firmware1 = {}}
    self.upgrade_instance.before_upgrade_version = '1.0.0'
    
    -- Mock upgrade_process返回错误
    local original_process = mock_upgrade_process.network_adapter_upgrade_process
    mock_upgrade_process.network_adapter_upgrade_process = function()
        return upgrade_defs.RET.ERR
    end
    
    self.upgrade_instance:on_upgrade_process(
        {},
        1,
        'Nic',
        '/tmp/firmware.tar',
        {}
    )
    
    -- 应该返回错误
    local process_reply = nil
    for _, call in ipairs(client_calls) do
        if call.method == 'ProcessReply' then
            process_reply = call
            break
        end
    end
    lu.assertNotNil(process_reply)
    lu.assertEquals(process_reply.ret_code, upgrade_defs.RET.ERR)
    
    -- 资源应该被清理
    lu.assertEquals(self.upgrade_instance.is_network_adapter_upgrading, false)
    lu.assertEquals(self.upgrade_instance.before_upgrade_version, '')
    
    -- 恢复原始函数
    mock_upgrade_process.network_adapter_upgrade_process = original_process
end

-- 测试on_upgrade_process - upgrade_process抛出异常
function TEST_Network_Adapter_Upgrade:test_on_upgrade_process_exception()
    self.upgrade_instance.cfgs = {Firmware1 = {}}
    
    -- Mock upgrade_process抛出异常
    local original_process = mock_upgrade_process.network_adapter_upgrade_process
    mock_upgrade_process.network_adapter_upgrade_process = function()
        error('process exception')
    end
    
    self.upgrade_instance:on_upgrade_process(
        {},
        1,
        'Nic',
        '/tmp/firmware.tar',
        {}
    )
    
    -- 应该捕获异常并返回错误
    local process_reply = nil
    for _, call in ipairs(client_calls) do
        if call.method == 'ProcessReply' then
            process_reply = call
            break
        end
    end
    lu.assertNotNil(process_reply)
    lu.assertEquals(process_reply.ret_code, upgrade_defs.RET.ERR)
    
    -- 恢复原始函数
    mock_upgrade_process.network_adapter_upgrade_process = original_process
end

-- 测试on_upgrade_finish - 非Nic类型固件
function TEST_Network_Adapter_Upgrade:test_on_upgrade_finish_not_nic_firmware()
    self.upgrade_instance:on_upgrade_finish(
        {},
        1,
        'Bmc',
        {}
    )
    
    -- 不应该有任何client调用
    lu.assertEquals(#client_calls, 0)
end

-- 测试on_upgrade_finish - 成功场景
function TEST_Network_Adapter_Upgrade:test_on_upgrade_finish_success()
    self.upgrade_instance.is_network_adapter_upgrading = true
    self.upgrade_instance.cfgs = {test = 1}
    
    self.upgrade_instance:on_upgrade_finish(
        {},
        1,
        'Nic',
        {}
    )
    
    -- 应该有UpdateUpgradeStatus和FinishReply调用
    lu.assertTrue(#client_calls >= 2)
    
    -- 检查UpdateUpgradeStatus调用
    local has_status_update = false
    for _, call in ipairs(client_calls) do
        if call.method == 'UpdateUpgradeStatus' then
            has_status_update = true
            lu.assertEquals(call.progress, 90)
        end
    end
    lu.assertTrue(has_status_update)
    
    -- 检查FinishReply
    local finish_reply = nil
    for _, call in ipairs(client_calls) do
        if call.method == 'FinishReply' then
            finish_reply = call
            break
        end
    end
    lu.assertNotNil(finish_reply)
    lu.assertEquals(finish_reply.firmware_type, 'Nic')
    lu.assertEquals(finish_reply.ret_code, upgrade_defs.RET.OK)
    
    -- 资源应该被清理
    lu.assertEquals(self.upgrade_instance.is_network_adapter_upgrading, false)
    lu.assertEquals(#self.upgrade_instance.cfgs, 0)
end

-- 测试on_upgrade_finish - upgrade_finish抛出异常
function TEST_Network_Adapter_Upgrade:test_on_upgrade_finish_exception()
    -- Mock upgrade_finish抛出异常
    local original_finish = mock_upgrade_process.network_adapter_upgrade_finish
    mock_upgrade_process.network_adapter_upgrade_finish = function()
        error('finish failed')
    end
    
    self.upgrade_instance:on_upgrade_finish(
        {},
        1,
        'Nic',
        {}
    )
    
    -- 应该捕获异常并返回错误
    local finish_reply = nil
    for _, call in ipairs(client_calls) do
        if call.method == 'FinishReply' then
            finish_reply = call
            break
        end
    end
    lu.assertNotNil(finish_reply)
    lu.assertEquals(finish_reply.ret_code, upgrade_defs.RET.ERR)
    
    -- 恢复原始函数
    mock_upgrade_process.network_adapter_upgrade_finish = original_finish
end

-- 测试on_active_process - 正在升级中
function TEST_Network_Adapter_Upgrade:test_on_active_process_is_upgrading()
    self.upgrade_instance.is_network_adapter_upgrading = true
    
    self.upgrade_instance:on_active_process(
        {},
        1,
        'Nic',
        {}
    )
    
    -- 应该返回错误
    lu.assertEquals(#client_calls, 1)
    lu.assertEquals(client_calls[1].method, 'ActiveProcessReply')
    lu.assertEquals(client_calls[1].ret_code, upgrade_defs.RET.ERR)
end

-- 测试on_active_process - 正在激活中
function TEST_Network_Adapter_Upgrade:test_on_active_process_is_activing()
    self.upgrade_instance.is_network_adapter_activing = true
    
    self.upgrade_instance:on_active_process(
        {},
        1,
        'Nic',
        {}
    )
    
    -- 应该返回错误
    lu.assertEquals(#client_calls, 1)
    lu.assertEquals(client_calls[1].method, 'ActiveProcessReply')
    lu.assertEquals(client_calls[1].ret_code, upgrade_defs.RET.ERR)
end

-- 测试on_active_process - 成功场景
function TEST_Network_Adapter_Upgrade:test_on_active_process_success()
    self.upgrade_instance:on_active_process(
        {},
        1,
        'Nic',
        {}
    )
    
    -- 应该有ActiveProcessReply调用
    lu.assertEquals(#client_calls, 1)
    lu.assertEquals(client_calls[1].method, 'ActiveProcessReply')
    lu.assertEquals(client_calls[1].ret_code, upgrade_defs.RET.OK)
    lu.assertEquals(client_calls[1].firmware_type, 'Nic')
end

-- 测试on_active_process - active_process抛出异常
function TEST_Network_Adapter_Upgrade:test_on_active_process_exception()
    -- Mock active_process抛出异常
    local original_active = mock_active_process.network_adapter_active_process
    mock_active_process.network_adapter_active_process = function()
        error('active failed')
    end
    
    self.upgrade_instance:on_active_process(
        {},
        1,
        'Nic',
        {}
    )
    
    -- 应该捕获异常并返回错误
    lu.assertEquals(#client_calls, 1)
    lu.assertEquals(client_calls[1].method, 'ActiveProcessReply')
    lu.assertEquals(client_calls[1].ret_code, upgrade_defs.RET.ERR)
    
    -- 恢复原始函数
    mock_active_process.network_adapter_active_process = original_active
end

-- 测试完整的升级流程
function TEST_Network_Adapter_Upgrade:test_full_upgrade_flow()
    -- 1. 准备阶段
    mock_network_adapter_firmware.collection.count = 1
    mock_network_adapter_firmware_objects['test'] = {
        ComponentID = 1,
        ComponentIDEx = 2,
        FirmwareVersion = '1.0.0'
    }
    
    self.upgrade_instance:on_upgrade_prepare(
        {},
        1,
        'Nic',
        '/tmp/test.cfg',
        '/tmp/test.hpm',
        {}
    )
    
    -- 检查准备阶段成功
    local prepare_reply = nil
    for _, call in ipairs(client_calls) do
        if call.method == 'PrepareReply' then
            prepare_reply = call
            break
        end
    end
    lu.assertNotNil(prepare_reply)
    lu.assertEquals(prepare_reply.ret_code, upgrade_defs.RET.OK)
    lu.assertEquals(self.upgrade_instance.is_network_adapter_upgrading, true)
    
    -- 2. 执行阶段
    client_calls = {} -- 清空调用记录
    self.upgrade_instance.cfgs = {Firmware1 = {}}
    
    self.upgrade_instance:on_upgrade_process(
        {},
        1,
        'Nic',
        '/tmp/firmware.tar',
        {}
    )
    
    local process_reply = nil
    for _, call in ipairs(client_calls) do
        if call.method == 'ProcessReply' then
            process_reply = call
            break
        end
    end
    lu.assertNotNil(process_reply)
    lu.assertEquals(process_reply.ret_code, upgrade_defs.RET.OK)
    
    -- 3. 完成阶段
    client_calls = {} -- 清空调用记录
    
    self.upgrade_instance:on_upgrade_finish(
        {},
        1,
        'Nic',
        {}
    )
    
    local finish_reply = nil
    for _, call in ipairs(client_calls) do
        if call.method == 'FinishReply' then
            finish_reply = call
            break
        end
    end
    lu.assertNotNil(finish_reply)
    lu.assertEquals(finish_reply.ret_code, upgrade_defs.RET.OK)
    lu.assertEquals(self.upgrade_instance.is_network_adapter_upgrading, false)
end

-- 测试信号订阅回调
function TEST_Network_Adapter_Upgrade:test_signal_callbacks_registered()
    local instance = network_adapter_upgrade
    instance:init({})
    
    -- 验证回调函数已注册
    lu.assertNotNil(client_callbacks.on_prepare)
    lu.assertNotNil(client_callbacks.on_process)
    lu.assertNotNil(client_callbacks.on_finish)
    lu.assertNotNil(client_callbacks.on_active)
end

-- 测试资源清理功能
function TEST_Network_Adapter_Upgrade:test_clear_resources()
    -- 设置初始状态
    self.upgrade_instance.cfgs = {test = 1}
    self.upgrade_instance.upgrade_list = {item1 = 1}
    self.upgrade_instance.before_upgrade_version = 'test_version'
    self.upgrade_instance.is_network_adapter_upgrading = true
    self.upgrade_instance.is_network_adapter_activing = true
    self.upgrade_instance.hpm_path = '/tmp/test.hpm'
    self.upgrade_instance.power_state = 'PowerOn'
    self.upgrade_instance.poweron_locked = false
    
    -- 执行finish清理资源
    self.upgrade_instance:on_upgrade_finish(
        {},
        1,
        'Nic',
        {}
    )
    
    -- 资源应该被清理
    lu.assertEquals(#self.upgrade_instance.cfgs, 0)
    lu.assertEquals(#self.upgrade_instance.upgrade_list, 0)
    lu.assertEquals(self.upgrade_instance.before_upgrade_version, '')
    lu.assertEquals(self.upgrade_instance.is_network_adapter_upgrading, false)
    lu.assertEquals(self.upgrade_instance.is_network_adapter_activing, false)
    lu.assertEquals(self.upgrade_instance.hpm_path, '')
    lu.assertEquals(self.upgrade_instance.power_state, nil)
end

return TEST_Network_Adapter_Upgrade
