-- 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 skynet = require 'skynet'
local fw_upgrade = require 'unit_manager.class.logic_fw.upgrade.fw_upgrade'
local fpga_upgrade = require 'unit_manager.class.logic_fw.fpga.fpga_upgrade'
local lu = require 'luaunit'
local fw_mgmt_client = require 'general_hardware.client'
local signal = require 'unit_manager.class.logic_fw.signal'
local fpga_signal = require 'unit_manager.class.logic_fw.fpga.fpga_signal'
local factory = require 'factory'
local fructl = require 'mcu.upgrade.fructl_handler'
local valid_handle = require 'unit_manager.class.logic_fw.upgrade.valid'
local fpga_process = require 'unit_manager.class.logic_fw.fpga.fpga_process'
local fpga_self_test = require 'unit_manager.class.logic_fw.fpga.fpga_self_test'
local process_handle = require 'unit_manager.class.logic_fw.upgrade.process'
local vos = require 'utils.vos'
local defs = require 'unit_manager.class.logic_fw.comm_defs'
local unit_manager = require 'unit_manager.unit_manager'

local active_success = false

local SYSTEM_ID = 1

local manager = {
    logic_fw = {
        [1] = {
            csr = {
                Name = "L1_FPGA"
            },
            position = "010103",
            system_id = SYSTEM_ID,
            valid_condition = defs.VALID_CONDITION.POWER_OFF,
            smc_chip = {
                ['bmc.kepler.Chip'] = {
                    SetAccessibility = function ()
                    end
                }
            },
            check_update_ver = function()
            end
        }
    },
    exp_boards = {
        [1] = {
            position = "010103",
            task_update_logic_version = function()
            end
        }
    }
}

TestLogicalFwSignal = {}

function TestLogicalFwSignal:setupClass()
    skynet.fork = function(cb)
        cb()
    end

    self.old_prepare_upgrade = fw_upgrade.prepare_upgrade
    fw_upgrade.prepare_upgrade = function()
    end
    self.old_process_upgrade = fw_upgrade.process_upgrade
    fw_upgrade.process_upgrade = function()
    end
    self.old_finish_upgrade = fw_upgrade.finish_upgrade
    fw_upgrade.finish_upgrade = function()
        return true
    end

    fpga_upgrade.active_process = function()
        return true
    end

    self.old_upgrade_fpga_by_flash = process_handle.upgrade_fpga_by_flash
    process_handle.upgrade_fpga_by_flash = function(self, fpga_signal, file_path)
        if file_path == '1' then
            return 0
        end
        return -1
    end

    self.old_upgrade_component_cpld = process_handle.upgrade_component_cpld
    process_handle.upgrade_component_cpld = function(self, db, system_id, 
    fw_list, cfg_list, file_path, upgrade_list, hot_upgrade)
        if db == 1 then
            return 0
        end
        return -1
    end

    self.old_get_instance = fpga_self_test.get_instance
    fpga_self_test.get_instance = function()
        return {
            get_fpga_self_test_result = function()
                return 0
            end
        }
    end

    self.old_finish_upgrade = fpga_upgrade.finish_upgrade
    fpga_upgrade.finish_upgrade = function()
    end

    self.old_get_file_accessible = vos.get_file_accessible
    vos.get_file_accessible = function(file_path)
        if file_path ~= '/dev/mtd0' then
            return 0
        end
    end

    self.old_validate_upgarde_process = process_handle.validate_upgarde_process
    process_handle.validate_upgarde_process = function(self, fw_list, cfg_list, file_path)
        if #fw_list == 0 then
            return false
        end
        return true
    end

    self.old_cpld_valid = fw_upgrade.cpld_valid
    fw_upgrade.cpld_valid = true

    fw_mgmt_client.FirmwareActiveFirmwareActiveUpdateActiveStatus = function()
    end

    fw_mgmt_client.FirmwareActiveFirmwareActiveActiveProcessReply = function()
        -- 生效流程进入此函数表示成功，将结果置为true
        active_success = true
    end

    factory.get_obj = function()
        return manager
    end
    fw_mgmt_client.UpdateServiceUpdateServiceUpdateUpgradeStatus = function()
    end
end

function TestLogicalFwSignal:teardownClass() 
    fw_upgrade.cpld_valid = self.old_cpld_valid
    fw_upgrade.prepare_upgrade = self.old_prepare_upgrade
    fw_upgrade.process_upgrade = self.old_process_upgrade
    fw_upgrade.finish_upgrade = self.old_finish_upgrade
    process_handle.upgrade_fpga_by_flash = self.old_upgrade_fpga_by_flash
    process_handle.upgrade_component_cpld = self.old_upgrade_component_cpld
    fpga_self_test.get_instance = self.old_get_instance
    fpga_upgrade.finish_upgrade = self.old_finish_upgrade
    vos.get_file_accessible = self.old_get_file_accessible
    process_handle.validate_upgarde_process = self.old_validate_upgarde_process
end

-- 测试CPLD升级生效流程，生效条件为下电
function TestLogicalFwSignal:test_active_callback_power_off()
    active_success = false
    fw_mgmt_client.GetFirmwareActiveInfoFirmwareActiveInfoObject= function()
        return {ActiveCondition = defs.VALID_CONDITION_STR.POWER_OFF}
    end
    signal.active_callback(_, SYSTEM_ID, 'CPLD')
    lu.assertEquals(active_success, true)
    lu.assertEquals(fw_upgrade.cpld_valid, true)
end

-- 测试CPLD升级生效流程，生效条件为复位BMC
function TestLogicalFwSignal:test_active_callback_reset_bmc()
    local smc_accessibility_change_flag = false
    local temp_logic_fw = signal.fw_list
    signal.fw_list = manager.logic_fw
    fw_mgmt_client.GetFirmwareActiveInfoFirmwareActiveInfoObject= function()
        return {ActiveCondition = defs.VALID_CONDITION_STR.RESET_BMC}
    end

    active_success = false
    signal.active_callback(_, SYSTEM_ID, 'CPLD')
    lu.assertEquals(active_success, true)
    lu.assertEquals(smc_accessibility_change_flag, false)
    lu.assertEquals(fw_upgrade.cpld_valid, true)

    active_success = false
    signal.fw_list[1].valid_condition = defs.VALID_CONDITION.RESET_BMC
    signal.fw_list[1].smc_chip['bmc.kepler.Chip'].SetAccessibility = function ()
        smc_accessibility_change_flag = true
    end
    signal.active_callback(_, SYSTEM_ID, 'CPLD')
    lu.assertEquals(active_success, true)
    lu.assertEquals(smc_accessibility_change_flag, true)
    lu.assertEquals(fw_upgrade.cpld_valid, true)

    signal.fw_list = temp_logic_fw
end

-- 测试CPLD升级生效流程，生效条件获取失败
function TestLogicalFwSignal:test_active_callback_get_fail()
    local smc_accessibility_change_flag = false
    local temp_logic_fw = signal.fw_list
    signal.fw_list = manager.logic_fw
    fw_mgmt_client.GetFirmwareActiveInfoFirmwareActiveInfoObject= nil

    active_success = false
    signal.fw_list[1].valid_condition = defs.VALID_CONDITION.RESET_BMC
    signal.fw_list[1].smc_chip['bmc.kepler.Chip'].SetAccessibility = function ()
        smc_accessibility_change_flag = true
    end
    signal.active_callback(_, SYSTEM_ID, 'CPLD')
    lu.assertEquals(active_success, true)
    lu.assertEquals(smc_accessibility_change_flag, false)
    lu.assertEquals(fw_upgrade.cpld_valid, true)

    signal.fw_list = temp_logic_fw
end

-- 测试CPLD升级prepare流程
function TestLogicalFwSignal:test_upgrade_prepare_callback()
    local ok, err = pcall(signal.upgrade_prepare_callback, _, SYSTEM_ID, 'Cpld', '')
    lu.assertEquals(ok, true, err)
end

-- 测试CPLD升级process流程
function TestLogicalFwSignal:test_upgrade_process_callback()
    local ok = pcall(signal.upgrade_process_callback, _, SYSTEM_ID, 'Cpld', '')
    lu.assertEquals(ok, true)
end

-- 测试CPLD升级finish流程
function TestLogicalFwSignal:test_upgrade_finish_callback()
    local temp_handle = valid_handle.get_system_id_list
    fructl.get_chassis_power_status = function()
        return "ON"
    end
    valid_handle.get_validating_flag = function()
        return false
    end
    valid_handle.get_system_id_list = function()
        return { [1] = 1 }
    end
    fw_mgmt_client.UpdateServiceUpdateServiceFinishReply = function()
    end
    local ok = pcall(signal.upgrade_finish_callback, _, 255, 'Cpld')
    lu.assertEquals(ok, true)

    ok = pcall(signal.upgrade_finish_callback, _, SYSTEM_ID, 'Cpld')
    lu.assertEquals(ok, true)

    fructl.get_chassis_power_status = function()
        return "OFF"
    end
    valid_handle.get_validating_flag = function()
        return true
    end
    fw_upgrade.finish_upgrade = function()
        return true
    end
    fw_mgmt_client.UpdateServiceUpdateServiceUpdateUpgradeStatus = function()
    end
    fw_mgmt_client.UpdateServiceUpdateServiceFinishReply = function()
    end
    signal.db = {
        CustomizeSign = function()
        end
    }
    signal.fw_list = {
        [1] = {
            valid_mode = 2
        }
    }
    signal.upg_cfg_list = {
        [1] = {
            check_fw_uid_exist = function()
                return true
            end
        }
    }
    ok = pcall(signal.upgrade_finish_callback, _, SYSTEM_ID, 'Cpld')
    lu.assertEquals(ok, true)

    signal.fw_list = {
        [1] = {
            valid_mode = 3
        }
    }
    ok = pcall(signal.upgrade_finish_callback, _, SYSTEM_ID, 'Cpld')
    lu.assertEquals(ok, true)

    valid_handle.get_system_id_list = temp_handle
end

-- 测试CPLD升级finish注册生效条件与生效动作流程
function TestLogicalFwSignal:test_upgrade_finish_callback_register()
    local temp_handle = valid_handle.get_system_id_list
    local temp_logic_fw = signal.fw_list
    local register_active_flag = false
    signal.fw_list = manager.logic_fw
    valid_handle.get_validating_flag = function()
        return true
    end
    valid_handle.get_system_id_list = function()
        return { [1] = 1 }
    end
    fw_mgmt_client.UpdateServiceUpdateServiceFinishReply = function()
    end
    fructl.is_multihost_type = function()
        return false
    end
    signal.upg_cfg_list = {
        [1] = {
            name = 'Firmware1',
            uid = 0,
            check_fw_uid_exist = function()
                return true
            end
        }
    }

    -- 当前状态为上电，生效条件为复位BMC，应当注册生效条件
    fructl.get_power_status = function()
        return "ON"
    end
    signal.fw_list[1].valid_condition = defs.VALID_CONDITION.RESET_BMC
    fw_mgmt_client.FirmwareActiveFirmwareActiveRegisterActiveAction = function(fw_mgmt_client, ctx, para)
        if para[3].Value == defs.VALID_CONDITION_STR.RESET_BMC then
            register_active_flag = true
        end
    end
    local ok = pcall(signal.upgrade_finish_callback, _, SYSTEM_ID, 'Cpld', {FirmwareIndex = 'Firmware1'})
    lu.assertEquals(ok, true)
    lu.assertEquals(register_active_flag, true)

    -- 当前状态为上电，生效条件为下电，应当注册生效条件
    register_active_flag = false
    signal.fw_list[1].valid_condition = defs.VALID_CONDITION.POWER_OFF
    fw_mgmt_client.FirmwareActiveFirmwareActiveRegisterActiveAction = function(fw_mgmt_client, ctx, para)
        if para[3].Value == defs.VALID_CONDITION_STR.POWER_OFF then
            register_active_flag = true
        end
    end
    ok = pcall(signal.upgrade_finish_callback, _, SYSTEM_ID, 'Cpld', {FirmwareIndex = 'Firmware1'})
    lu.assertEquals(ok, true)
    lu.assertEquals(register_active_flag, true)

    -- 当前状态为下电，生效条件为复位BMC，应当注册生效条件
    register_active_flag = false
    fructl.get_power_status = function()
        return "OFF"
    end
    signal.fw_list[1].valid_condition = defs.VALID_CONDITION.RESET_BMC
    fw_mgmt_client.FirmwareActiveFirmwareActiveRegisterActiveAction = function(fw_mgmt_client, ctx, para)
        if para[3].Value == defs.VALID_CONDITION_STR.RESET_BMC then
            register_active_flag = true
        end
    end
    ok = pcall(signal.upgrade_finish_callback, _, SYSTEM_ID, 'Cpld', {FirmwareIndex = 'Firmware1'})
    lu.assertEquals(ok, true)
    lu.assertEquals(register_active_flag, true)

    signal.fw_list = temp_logic_fw
    valid_handle.get_system_id_list = temp_handle
end

-- 测试FPGA升级生效流程
function TestLogicalFwSignal:test_fpga_active_callback()
    --FpgaLoadResetb不为0时代表需要生效
    active_success = false
    fpga_signal.active_callback(_, SYSTEM_ID, 'FPGA')
    lu.assertEquals(active_success, true)

    active_success = false
    fpga_signal.active_callback(_, SYSTEM_ID, 'FPGA')
    lu.assertEquals(active_success, true)
end

-- 测试获取固件信息
function TestLogicalFwSignal:test_get_fpga_type()
    local file_path = "/dev/shm/upgrade/Firmware1"
    local ok = pcall(function()
        fpga_signal.get_fpga_type(self, file_path)
    end)
    lu.assertEquals(ok, false)
end

-- 测试fpga flash升级finish流程
function TestLogicalFwSignal:test_upgrade_component_fpga()
    local fpga_signal = {
        fpga_upgrade_type = 'SFC',
        fw_list = {
            {
                system_id = 1,
                csr = {
                    Name = 'FPGA'
                }
            }
        },
        upg_cfg_list = {
            {
                name = "Firmware1",
                uid = 111,
                check_fw_uid_exist = function(fw)
                    return 0
                end
            }
        }
    }
    local file_path = "1"
    local ok = fpga_process:upgrade_component_fpga(fpga_signal, file_path)
    lu.assertEquals(ok, 0)
end

-- 测试fpga flash升级finish flash fail流程
function TestLogicalFwSignal:test_upgrade_component_fpga_flash_err()
    local file_path = "2"
    local fpga_signal = {
        fpga_upgrade_type = 'SFC',
        fw_list = {
            {
                system_id = 1,
                csr = {
                    Name = 'FPGA'
                }
            }
        },
        upg_cfg_list = {
            {
                name = "Firmware1",
                uid = 111,
                check_fw_uid_exist = function(fw)
                    return 0
                end
            }
        }
    }
    local ok = fpga_process:upgrade_component_fpga(fpga_signal, file_path)
    lu.assertEquals(ok, -1)
end

-- 测试fpga flash升级finish jtag fail流程
function TestLogicalFwSignal:test_upgrade_component_fpga_jtag_fail()
    local fpga_signal = {
        fpga_upgrade_type = 'JTAG',
        db = 0,
        fw_list = {
            {
                system_id = 1,
                csr = {
                    Name = 'FPGA'
                }
            }
        },
        upg_cfg_list = {
            {
                name = "Firmware1",
                uid = 111,
                check_fw_uid_exist = function(fw)
                    return 0
                end
            }
        }
    }
    local file_path = "2"
    local ok = fpga_process:upgrade_component_fpga(fpga_signal, file_path)
    lu.assertEquals(ok, -1)
end

-- 测试fpga flash升级finish jtag fail流程
function TestLogicalFwSignal:test_upgrade_component_fpga_jtag()
    local file_path = "1"
    local fpga_signal = {
        fpga_upgrade_type = 'JTAG',
        db = 1,
        fw_list = {
            {
                system_id = 1,
                csr = {
                    Name = 'FPGA'
                }
            }
        },
        upg_cfg_list = {
            {
                name = "Firmware1",
                uid = 111,
                check_fw_uid_exist = function(fw)
                    return 0
                end
            }
        }
    }
    local ok = fpga_process:upgrade_component_fpga(fpga_signal, file_path)
    lu.assertEquals(ok, 0)
end