-- Copyright (c) 2024 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 upgrade_service_handle = require 'mcu.upgrade.upgrade_service.upgrade_service_handle'
local fw_mgmt = require 'general_hardware.client'
local context = require 'mc.context'
local ini_parser = require 'mc.v2_persistence'
local upgrade_service_vrd = require 'mcu.upgrade.upgrade_service.upgrade_service_vrd'
local upgrade_service_mcu = require 'mcu.upgrade.upgrade_service.upgrade_service_mcu'
local upgrade_service_comm = require 'mcu.upgrade.upgrade_service.upgrade_service_comm'
local upgrade_object = require 'mcu.upgrade.upgrade_object'
local fructl = require 'mcu.upgrade.fructl_handler'
local parse_cfg = require 'mcu.upgrade.parser_cfg'
local mdb = require 'mc.mdb'
local utils = require 'mc.utils'
local vos = require 'utils.vos'
local utils_core = require 'utils.core'

TestMcuUpgService = {}

local RET_OK <const> = 0
local RET_ERR <const> = -1
local IN_UPGRADING <const> = 36

local upgrade_ret

local old_function ={}
local upgrade_object_new = upgrade_object.new

local cfg = {}

local function stub_functions_2()
    upgrade_service_handle.is_activing =false
    upgrade_service_vrd.is_vrd_upgrading = false
    upgrade_service_mcu.get_instance().is_mcu_upgrading = false

    old_function.get_cfgs = parse_cfg.get_cfgs
    parse_cfg.get_cfgs = function ()
        return 'Firmware1', cfg
    end

    old_function.save_cfg = parse_cfg.save_cfg
    parse_cfg.save_cfg = function ()
    end

    old_function.load_file = ini_parser.load_file
    local data = {
        Firmware1 = {
            Uid = true
        }
    }
    ini_parser.load_file = function()
        return data
    end

    old_function.PFileFileChown = fw_mgmt.PFileFileChown
    fw_mgmt.PFileFileChown = function()
        return true
    end

    upgrade_service_vrd.is_vrd_upgrading = false

    old_function.get_power_status = fructl.get_power_status
    fructl.get_power_status = function ()
        return 'ON'
    end

    old_function.get_sub_objects = mdb.get_sub_objects
    mdb.get_sub_objects = function()
        local obj_list = {
            [1] = {
                pcall= {
                    SetPowerOnLock = function()
                    end
                }
            }
        }
        return obj_list
    end

    old_function.secure_tar_unzips = utils.secure_tar_unzip
    utils.secure_tar_unzip = function()
    end

    old_function.get_file_accessible = vos.get_file_accessible
    vos.get_file_accessible = function()
        return true
    end
end

local function stub_functions()
    stub_functions_2()
    old_function.dir = utils_core.dir
    utils_core.dir = function()
        return {
            'BCU_1_vrd.hpm'
        }
    end

    old_function.new = upgrade_object.new
    upgrade_object.new = function(mcu_obj, system_id, power_state)
        local obj = upgrade_object_new(mcu_obj, system_id, power_state)
        obj.upgrade_process = function()
            return 0
        end
        return obj
    end

    old_function.is_upgrade_obj_proc_finis = upgrade_service_comm.is_upgrade_obj_proc_finish
    upgrade_service_comm.is_upgrade_obj_proc_finish = function()
        return true
    end

    old_function.UpdateServiceUpdateServicePrepareReply = fw_mgmt.UpdateServiceUpdateServicePrepareReply
    fw_mgmt.UpdateServiceUpdateServicePrepareReply = function (_, _, _, _, _, prepare_ret, parameters)
        upgrade_ret = prepare_ret
    end

    old_function.UpdateServiceUpdateServiceProcessReply = fw_mgmt.UpdateServiceUpdateServiceProcessReply
    fw_mgmt.UpdateServiceUpdateServiceProcessReply = function (_, _, _, _, process_ret, parameters)
        upgrade_ret = process_ret
    end

    old_function.UpdateServiceUpdateServiceFinishReply = fw_mgmt.UpdateServiceUpdateServiceFinishReply
    fw_mgmt.UpdateServiceUpdateServiceFinishReply = function (_, _, _, _, finish_ret, parameters)
        upgrade_ret = finish_ret
    end

    old_function.FirmwareActiveFirmwareActiveActiveProcessReply = fw_mgmt.FirmwareActiveFirmwareActiveActiveProcessReply
    fw_mgmt.FirmwareActiveFirmwareActiveActiveProcessReply = function (_, _, _, _, _)
    end

    old_function.FirmwareActiveFirmwareActiveRegisterActiveAction =
        fw_mgmt.FirmwareActiveFirmwareActiveRegisterActiveAction
    fw_mgmt.FirmwareActiveFirmwareActiveRegisterActiveAction = function()
    end
end

local function recover_functions()
    parse_cfg.get_cfgs = old_function.get_cfgs
    parse_cfg.save_cfg = old_function.save_cfg
    ini_parser.load_file = old_function.load_file
    fw_mgmt.PFileFileChown = old_function.PFileFileChown
    upgrade_service_vrd.is_vrd_upgrading = false
    fructl.get_power_status = old_function.get_power_status
    mdb.get_sub_objects = old_function.get_sub_objects
    utils.secure_tar_unzip = old_function.secure_tar_unzips
    vos.get_file_accessible = old_function.get_file_accessible
    utils_core.dir = old_function.dir
    upgrade_object.new = old_function.new
    upgrade_service_comm.is_upgrade_obj_proc_finish = old_function.is_upgrade_obj_proc_finis
    fw_mgmt.UpdateServiceUpdateServicePrepareReply = old_function.UpdateServiceUpdateServicePrepareReply
    fw_mgmt.UpdateServiceUpdateServiceProcessReply = old_function.UpdateServiceUpdateServiceProcessReply
    fw_mgmt.UpdateServiceUpdateServiceFinishReply = old_function.UpdateServiceUpdateServiceFinishReply
    fw_mgmt.FirmwareActiveFirmwareActiveActiveProcessReply = old_function.FirmwareActiveFirmwareActiveActiveProcessReply
    fw_mgmt.FirmwareActiveFirmwareActiveRegisterActiveAction =
        old_function.FirmwareActiveFirmwareActiveRegisterActiveAction
end

local mcu_collection = {
    [1] =
    {
        get_system_id = function ()
            return 1
        end,
        get_uid = function ()
            return '111'
        end,
        mcu = {
            uid = '111',
            SubCompList = {
                {
                    Type = 0,
                    repeat_get_version = function()
                        return '0.01'
                    end,
                    set_major_version = function()
                    end,
                    set_minor_version = function()
                    end,
                    set_revision = function()
                    end,
                    ge_component_major_version = function()
                        return '0.01'
                    end
                }
            },
            LockChip = {
                SetLockStatus = function()
                    return 0
                end,
                LockStatus = 0
            }
        },
        chip_lock_supported = function()
            return true
        end,
        chip_lock = function()
            return true, 0
        end,
        chip_unlock = function()
            return true
        end,
        get_position = function()
        end,
        update_sub_component_info_list = function()
        end,
        vrd_info_changed = {
            emit = function()
            end
        },
        update_firmware_version = function()
        end,
        set_mcu_major_version = function()
        end,
        set_mcu_minor_version = function()
        end,
        set_mcu_revision = function()
        end
    }
}
local function stub_mcu_upg_instances()
    upgrade_service_mcu.get_instance().mcu_collection = mcu_collection
    cfg = {
        Firmware1 =
        {
            name = 'Firmware1',
            component_id = 35,
            component_idex = 1,
            uid_list = {'111'}
        }
    }
end

function TestMcuUpgService:test_upgrade_mcu()
    stub_mcu_upg_instances()
    stub_functions()
    upgrade_service_handle:on_upgrade_prepare(context.new(), 1, 'Mcu', '', '', {})
    lu.assertEquals(upgrade_ret, RET_OK)
    upgrade_service_handle:on_upgrade_process(context.new(), 1, 'Mcu', '/dev/shm/upgrad/valid/123456/Firmware1', {})
    lu.assertEquals(upgrade_ret, RET_OK)
    upgrade_service_handle:on_upgrade_finish(context.new(), 1, 'Mcu', {})
    lu.assertEquals(upgrade_ret, RET_OK)
    recover_functions()
end

--测试有其他mcu正在升级
function TestMcuUpgService:test_is_upgrading_mcu()
    stub_mcu_upg_instances()
    stub_functions()
    upgrade_service_mcu.get_instance().is_mcu_upgrading = true
    upgrade_service_handle:on_upgrade_prepare(context.new(), 1, 'Mcu', '', '', {})
    lu.assertEquals(upgrade_ret, IN_UPGRADING)
    upgrade_service_mcu.get_instance().is_mcu_upgrading = false
    recover_functions()
end

--测试串行升级
function TestMcuUpgService:test_serial_upgrade_mcu()
    stub_mcu_upg_instances()
    stub_functions()
    old_function.SetLockStatus = upgrade_service_mcu.get_instance().mcu_collection[1].mcu.LockChip.SetLockStatus
    upgrade_service_mcu.get_instance().mcu_collection[1].mcu.LockChip.SetLockStatus = nil
    upgrade_service_handle:on_upgrade_prepare(context.new(), 1, 'Mcu', '', '', {})
    lu.assertEquals(upgrade_ret, RET_OK)
    upgrade_service_handle:on_upgrade_process(context.new(), 1, 'Mcu', '/dev/shm/upgrad/valid/123456/Firmware1', {})
    lu.assertEquals(upgrade_ret, RET_OK)
    recover_functions()
    upgrade_service_mcu.get_instance().mcu_collection[1].mcu.LockChip.SetLockStatus = old_function.SetLockStatus
end