-- 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_service_obj = require 'mcu.upgrade.upgrade_service.upgrade_service_object'
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'
local upgrade_subject = require 'upgrade_subject.upgrade_subject'

TestUpgServicehandler = {}

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

local upgrade_ret
local active_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 (_, _, _, _, active1_ret)
        active_ret = active1_ret
    end

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

    upgrade_subject.get_instance().upgrade_observers = {}
    upgrade_subject.get_instance().active_observers = {}
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

function TestUpgServicehandler:test_upgrade_init()
    stub_functions()
    fw_mgmt.SubscribeUpdateServiceUpdateServiceUpgradePrepareSignal = function()
    end
    fw_mgmt.SubscribeUpdateServiceUpdateServiceUpgradeProcessSignal = function()
    end
    fw_mgmt.SubscribeUpdateServiceUpdateServiceUpgradeFinishSignal = function()
    end
    fw_mgmt.SubscribeFirmwareActiveFirmwareActiveActiveProcessSignal = function()
    end
    upgrade_service_handle:init(bus, {}, {})
    recover_functions()
end

function TestUpgServicehandler:test_unallowed_upgrade()
    local ok,err = pcall(upgrade_service_handle.on_upgrade_prepare, upgrade_service_handle,
        context.new(), 1, 'aaa', '', '', {})
    lu.assertEquals(ok, true)
    lu.assertEquals(err, nil)
    ok,err = pcall(upgrade_service_handle.on_upgrade_process, upgrade_service_handle,
        context.new(), 1, 'aaa', '/dev/shm/upgrad/valid/123456/Firmware1')
    lu.assertEquals(ok, true)
    lu.assertEquals(err, nil)
    ok,err = pcall(upgrade_service_handle.on_upgrade_finish, upgrade_service_handle, context.new(), 1, 'aaa')
    lu.assertEquals(ok, true)
    lu.assertEquals(err, nil)
    ok,err = pcall(upgrade_service_handle.on_active_process, upgrade_service_handle, context.new(), 1, 'aaa')
    lu.assertEquals(ok, true)
    lu.assertEquals(err, nil)
end

function TestUpgServicehandler:test_is_upgrading_active()
    stub_functions()
    upgrade_service_handle.is_activing =true
    upgrade_service_handle:on_active_process(context.new(), 1, 'VRD')
    lu.assertEquals(active_ret, RET_ERR)
    upgrade_service_handle.is_activing =false

    upgrade_service_vrd.is_vrd_upgrading = true
    upgrade_service_handle:on_active_process(context.new(), 1, 'VRD')
    lu.assertEquals(active_ret, RET_ERR)
    upgrade_service_vrd.is_vrd_upgrading = false
    recover_functions()
end

function TestUpgServicehandler:test_no_upgrade_service_obj()
    old_function.get_upgrade_service_obj = upgrade_service_obj.get_instance().get_upgrade_service_obj
    upgrade_service_obj.get_instance().get_upgrade_service_obj = function()
    end
    stub_functions()
    upgrade_service_handle:on_upgrade_prepare(context.new(), 1, 'Vrd', '', '')
    lu.assertEquals(upgrade_ret, RET_ERR)
    upgrade_service_handle:on_upgrade_process(context.new(), 1, 'Vrd', '/dev/shm/upgrad/valid/123456/Firmware1')
    lu.assertEquals(upgrade_ret, RET_ERR)
    upgrade_service_handle:on_upgrade_finish(context.new(), 1, 'Vrd')
    lu.assertEquals(upgrade_ret, RET_ERR)
    recover_functions()
    upgrade_service_obj.get_instance().get_upgrade_service_obj = old_function.get_upgrade_service_obj
end