-- 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_object = require 'mcu.upgrade.upgrade_object'
local file_sec = require 'utils.file'
local utils = require 'mc.utils'
local utils_core = require 'utils.core'

TestUpgradeobject = {}

local mcu_obj = {
    mcu = {
        Id = 'mcu1',
        RefChip = {},
        LockChip = {},
        Protocol = {}
    },
    device_name = 'CpuBoard1',
    name = 'mcu1'
}
upgrade_object.new(mcu_obj, 1, 'OFF')

local project_dir = os.getenv('PROJECT_DIR')
local file_path = project_dir .. '/test/unit/test_data/mcu/'
local file_name = file_path .. 'mcu.bin'
-- 打桩升级文件
utils.mkdir_with_parents(file_path, utils.S_IRUSR | utils.S_IXUSR | utils.S_IRGRP | utils.S_IXGRP)
local file = file_sec.open_s(file_name, "w+")
file:write('test data')
file:close()

local old_function = {}
local function stub_upgrade_object(board_type)
    old_function.get_ref_mcu = upgrade_object.get_ref_mcu
    upgrade_object.get_ref_mcu = function ()
        return {
            get_board_type = function () return board_type end,
            interface = {
                send_upgrade_file = function () end,
                send_acu_upgrade_file = function () end
            }
        }
    end

    old_function.get_ref_subcomp = upgrade_object.get_ref_subcomp
    upgrade_object.get_ref_subcomp = function ()
        return {Vendor = 0, Type = 0, Delay = 10}
    end
end

-- 测试传输升级文件
function TestUpgradeobject:test_send_upgrade_file()
    stub_upgrade_object('BCU')
    local upg_prog_cb = {}
    local upgrade_details = {dir = 'test', ever_send_file_success = 0}
    local ok = pcall(function()
        return upgrade_object:send_upgrade_file(file_name, upg_prog_cb, upgrade_details)
    end)
    lu.assertEquals(ok, true)
    upgrade_object.get_ref_mcu = old_function.get_ref_mcu
    upgrade_object.get_ref_subcomp = old_function.get_ref_subcomp

    stub_upgrade_object('ACU')
    ok = pcall(function()
        return upgrade_object:send_upgrade_file(file_name, upg_prog_cb, upgrade_details)
    end)
    utils.remove_file(file_name)
    lu.assertEquals(ok, true)
    upgrade_object.get_ref_mcu = old_function.get_ref_mcu
    upgrade_object.get_ref_subcomp = old_function.get_ref_subcomp
end

function TestUpgradeobject:test_get_send_params()
    local vendor = 2
    local fw_type = 2
    local board_type = 'BCU'

    local sub_comp = {}
    sub_comp.No = 0

    local ok = pcall(upgrade_object.get_send_params, upgrade_object, vendor, board_type, fw_type, sub_comp)
    lu.assertEquals(ok, true)
end

-- 测试升级文件路径
function TestUpgradeobject:test_get_file_path()
    old_function.get_ref_mcu = upgrade_object.get_ref_mcu
    old_function.chown_s = utils_core.chown_s
    old_function.check_real_path_s = file_sec.check_real_path_s
    file_sec.check_real_path_s = function(...) return -1 end
    utils_core.chown_s = function(...) return end
    upgrade_object.get_ref_mcu = function ()
        return {
            get_board_type = 'BCU',
            interface = {
                get_vendor_id = function (...) return 1 end
            }
        }
    end

    upgrade_object.interface_type = 'test'

    local ok = pcall(upgrade_object.get_file_path, upgrade_object, 'test')
    lu.assertEquals(ok, true)

    upgrade_object.get_ref_mcu = old_function.get_ref_mcu
    utils_core.chown_s = old_function.chown_s
    file_sec.check_real_path_s = old_function.check_real_path_s
end

-- 测试升级主流程
function TestUpgradeobject:test_retry_upgrade()
    old_function.get_ref_mcu = upgrade_object.get_ref_mcu
    old_function.is_upgradeable = upgrade_object.is_upgradeable
    old_function.send_upgrade_file = upgrade_object.send_upgrade_file
    old_function.get_file_path = upgrade_object.get_file_path
    old_function.wait_mcu_to_available = upgrade_object.wait_mcu_to_available
    old_function.take_upgrade_effect = upgrade_object.take_upgrade_effect
    old_function.exec_valid_action_with_condition = upgrade_object.exec_valid_action_with_condition
    old_function.update_firmware_version = upgrade_object.update_firmware_version
    upgrade_object.get_ref_mcu = function ()
        return {
            get_board_type = 'BCU',
            interface = {
                get_vendor_id = function (...) return 1 end,
                init_upgrade = function () return 0 end,
                start_upgrade = function () return 0 end
            }
        }
    end
    upgrade_object.interface_type = 'test'
    upgrade_object.is_upgradeable = function () return 0 end
    upgrade_object.send_upgrade_file = function () return 0 end
    upgrade_object.get_file_path = function () return 'test/00_01_00.bin' end
    upgrade_object.wait_mcu_to_available = function () return 0 end
    upgrade_object.take_upgrade_effect = function () return 0 end
    upgrade_object.exec_valid_action_with_condition = function () return 0 end
    upgrade_object.update_firmware_version = function () end

    local upgrade_details = {dir = 'test', ever_send_file_success = 0}
    local fw_info = {fw_obj = {id = 'MCU'}, fw_index = 1}
    local ok = pcall(upgrade_object.retry_upgrade, upgrade_object, upgrade_details, fw_info, {}, 1)
    lu.assertEquals(ok, true)

    upgrade_object.get_ref_mcu = old_function.get_ref_mcu
    upgrade_object.is_upgradeable = old_function.is_upgradeable
    upgrade_object.send_upgrade_file = old_function.send_upgrade_file
    upgrade_object.get_file_path = old_function.get_file_path
    upgrade_object.wait_mcu_to_available = old_function.wait_mcu_to_available
    upgrade_object.take_upgrade_effect = old_function.take_upgrade_effect
    upgrade_object.exec_valid_action_with_condition = old_function.exec_valid_action_with_condition
end
