-- 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 client = require 'general_hardware.client'
local upgrade = require "upgrade_subject.upgrade_subject"
local dpu_service = require 'dpu_service.dpu_service'
local upgrade_service_handle = require 'mcu.upgrade.upgrade_service.upgrade_service_handle'

local retimer_service = require 'retimer.upgrade.retimer_upg_service'
local sr_upg_service = require 'sr_upg_service.sr_upg_service'
local cpld_service = require 'unit_manager.class.logic_fw.signal'
local fpga_service = require 'unit_manager.class.logic_fw.fpga.fpga_signal'

local utils = require 'dpu_service.utils'
local parser_cfg = require 'sr_upg_service.parser_cfg'
local retimer_parser = require 'retimer.upgrade.parser_cfg'
local fructl = require 'mcu.upgrade.fructl_handler'
local cfg = require 'mcu.upgrade.parser_cfg'

local ini_parse = require 'mc.v2_persistence'


local function stub_function_list()
        -- 监听升级信号
        client.SubscribeUpdateServiceUpdateServiceUpgradePrepareSignal = function ()
        end
        client.SubscribeUpdateServiceUpdateServiceUpgradeProcessSignal = function ()
        end
        client.SubscribeUpdateServiceUpdateServiceUpgradeFinishSignal = function ()
        end
        client.SubscribeFirmwareActiveFirmwareActiveActiveProcessSignal = function ()
        end
        utils.get_cfgs = function ()
            return {}
        end
end

TestUpgradeSubject = {}

-- 测试用例描述：dpu升级流程
-- 预置条件：创建dpu服务，创建subject对象
-- 操作步骤：
-- 1.通过init注册observer
-- 2.模拟收到prepare/process/finish信号
-- 预期结果：1.observer注册正常；2.正确走入dpu prepare/process/finish流程
--[[
function TestUpgradeSubject:test_dpu_upgrade()
    stub_function_list()
    local subject_service = upgrade.new()
    subject_service:init()
    local dpu = dpu_service.new()
    dpu.test_flag = "dpu object"
    dpu:init({})

    local dpu_firmware_list = {"DPUMcu", "DPUCpld", "DPUVrd", "Mcu"}
    for i = 1, #dpu_firmware_list do
        local firmware_type = dpu_firmware_list[i]
        local dpu_observer = subject_service.upgrade_observers[firmware_type]
        if not dpu_observer then
            lu.assertIsTrue(dpu_firmware_list[i] == "Mcu")
        else
            lu.assertIsTrue(dpu_observer.test_flag == "dpu object")
        end
    end

    utils.get_firmware_uid = function ()
        return true
    end
    
    local ok = pcall(function()
        return subject_service:on_upgrade_prepare(_, 1, 'Mcu', '/dev/shm/upgrade/123456/name', _, _)
    end)
    lu.assertIsTrue(ok == true)

    dpu.upgradable_cfgs = {
        name = 'Firmware1',
        component_id = 1,
        component_id_ex = 2,
        board_id = 3
    }
    local ok2 = pcall(function()
        return subject_service:on_upgrade_process(_, 1, 'Mcu', '/dev/shm/upgrade/123456/name')
    end)
    lu.assertIsTrue(ok2 == true)
    local ok3 = pcall(function ()
        return subject_service:on_upgrade_finish(_, 1, 'Mcu')
    end)
    lu.assertIsTrue(ok3 == true)
end ]]

-- 测试用例描述：mcu升级流程
-- 预置条件：创建mcu服务，创建subject对象
-- 操作步骤：
-- 1.通过init注册observer
-- 2.模拟收到prepare/process/active信号
-- 预期结果：1.observer注册正常；2.正确走入mcu prepare/process/active流程
function TestUpgradeSubject:test_mcu_upgrade()
    stub_function_list()
    local subject_service = upgrade.new()
    subject_service:init()
    local mcu = upgrade_service_handle.new()
    mcu.test_flag = "mcu object"
    mcu:init({}, {}, {})

    local mcu_firmware_list = {"Mcu", "Vrd", "Vdm"}
    for i = 1, #mcu_firmware_list do
        local firmware_type = mcu_firmware_list[i]
        local mcu_observer = subject_service.upgrade_observers[firmware_type]
        lu.assertIsTrue(mcu_observer.test_flag == "mcu object")
    end
    local mcu_observer = subject_service.active_observers["VRD"]
    lu.assertIsTrue(mcu_observer.test_flag == "mcu object")

    utils.get_firmware_uid = function ()
        return false
    end

    local parameters = {ComponentID = 23, ComponentIDEx = 125}
    local ok = pcall(function ()
        return subject_service:on_upgrade_prepare(_, 1, 'Mcu',
            '/dev/shm/upgrade/123456/name', '/dev/shm/upgrade/hpm', parameters)
    end)
    lu.assertIsTrue(ok == true)

    mcu.mcu_upg_instances = {
        Mcu = {
            cfgs = {
                Firmware1 = {
                    name = 'Firmware1',
                    component_id = 29,
                    component_idex = 0
                }
            }
        }
    }

    local ok2 = pcall(function ()
        return subject_service:on_upgrade_process(_, 1, 'Mcu',
            '/dev/shm/upgrade/123456/name', '/dev/shm/upgrade/hpm', parameters)
    end)
    lu.assertIsTrue(ok2 == true)

    local ok3 = pcall(function ()
        return subject_service:on_active_process(_, 1, 'VRD', parameters)
    end)
    lu.assertIsTrue(ok3 == true)
end

-- 测试用例描述：sr升级流程
-- 预置条件：创建sr服务，创建subject对象
-- 操作步骤：
-- 1.通过init注册observer
-- 2.模拟收到prepare/process信号
-- 预期结果：1.observer注册正常；2.正确走入sr prepare/process流程
function TestUpgradeSubject:test_sr_upgrade()
    stub_function_list()
    local subject_service = upgrade.new()
    subject_service:init()

    local sr_service = sr_upg_service.new()
    sr_service.test_flag = "sr object"
    sr_service:init({})

    local observer = subject_service.upgrade_observers["HWSR"]
    lu.assertIsTrue(observer.test_flag == "sr object")

    parser_cfg.get_cfgs = function ()
        local cfgs = {}
        cfgs[1]={component_id_ex = 127}
        return cfgs
    end

    local parameters = {["ActiveMode"] = "Immediately", ComponentID = 23, ComponentIDEx = 135}
    local ok = pcall(function ()
        return subject_service:on_upgrade_prepare(_, 1, 'HWSR', '', _, parameters)
    end)
    lu.assertIsTrue(ok == true)

    local ok2 = pcall(function ()
        return subject_service:on_upgrade_process(_, 1, 'HWSR', '', _, parameters)
    end)
    lu.assertIsTrue(ok2 == false)
    local ok4 = pcall(function()
        return subject_service:on_upgrade_finish(_, 1, "HWSR", parameters)
    end)
    lu.assertIsTrue(ok4 == true)
    
    -- 异常分支
    local temp = pcall(function()
        subject_service:on_upgrade_prepare(_, 1, 'HHH', '', _, parameters)
    end)
    lu.assertIsTrue(temp == true)
    local temp1 = pcall(function()
        subject_service:on_upgrade_process(_, 1, 'HHH', '', _, parameters)
    end)
    lu.assertIsTrue(temp1 == false)
    local temp2 = pcall(function()
        subject_service:on_upgrade_finish(_, 1, "HHH", parameters)
    end)
    lu.assertIsTrue(temp2 == true)
end

-- 测试用例描述：retimer升级流程
-- 预置条件：创建retimer服务，创建subject对象
-- 操作步骤：
-- 1.通过init注册observer
-- 2.模拟收到prepare/process信号
-- 预期结果：1.observer注册正常；2.正确走入retimer prepare/process流程
function TestUpgradeSubject:test_retimer_upgrade()
    stub_function_list()
    local subject_service = upgrade.new()
    subject_service:init()

    local retimer = retimer_service.new()
    retimer.test_flag = "retimer object"
    retimer:init({}, {})

    local observer = subject_service.upgrade_observers["Retimer"]
    lu.assertIsTrue(observer.test_flag == "retimer object")

    retimer_parser.get_cfgs = function ()
        local cfgs = {}
        cfgs[1]={component_id_ex = 16753977}
        return cfgs
    end
    local parameters = {ComponentID = 23, ComponentIDEx = 145}
    local ok = pcall(function ()
        return subject_service:on_upgrade_prepare(_, 1, 'Retimer', '/dev/shm/upgrade/123456/name', parameters)
    end)
    lu.assertIsTrue(ok == true)
    local ok2 = pcall(function ()
        return subject_service:on_upgrade_process(_, 1, 'Retimer', '/dev/shm/upgrade/123456/name', parameters)
    end)
    lu.assertIsTrue(ok2 == true)
end

-- 测试用例描述：cpld升级流程
-- 预置条件：创建cpld服务，创建subject对象
-- 操作步骤：
-- 1.通过init注册observer
-- 2.模拟收到prepare/process/active信号
-- 预期结果：1.observer注册正常；2.正确走入cpld prepare/process/active流程
function TestUpgradeSubject:test_cpld_upgrade()
    stub_function_list()
    local subject_service = upgrade.new()
    subject_service:init()
    local cpld = cpld_service.init({}, {
        CustomizeSign = function()
        end
    }, {})
    cpld.test_flag = "cpld object"

    local firmware_list = {"Cpld", "BP_Cpld", "EXUCpld", "BCUCpld", "CLUCpld", "SEUCpld", "IEUCpld", "DPUCpld"}
    for i = 1, #firmware_list do
        local firmware_type = firmware_list[i]
        local observer = subject_service.upgrade_observers[firmware_type]
        lu.assertIsTrue(observer.test_flag == "cpld object")
    end
    local cpld_observer = subject_service.active_observers["CPLD"]
    lu.assertIsTrue(cpld_observer.test_flag == "cpld object")

    local parameters = {ComponentID = 23, ComponentIDEx = 155}
    local ok = pcall(function ()
        return subject_service:on_upgrade_prepare(_, 1, 'Cpld', '/dev/shm/upgrade/123456/name', parameters)
    end)
    lu.assertIsTrue(ok == true)
    local ok2 = pcall(function ()
        return subject_service:on_upgrade_process(_, 1, 'Cpld', '/dev/shm/upgrade/123456/name', parameters)
    end)
    lu.assertIsTrue(ok2 == true)
    local ok3 = pcall(function ()
        return subject_service:on_active_process(_, 1, 'CPLD')
    end)
    lu.assertIsTrue(ok3 == true)
end

-- 测试用例描述：fpga升级流程
-- 预置条件：创建fpga服务，创建subject对象
-- 操作步骤：
-- 1.通过init注册observer
-- 2.模拟收到prepare/process/active信号
-- 预期结果：1.observer注册正常；2.正确走入fpga prepare/process/active流程
function TestUpgradeSubject:test_fpga_upgrade()
    stub_function_list()
    local subject_service = upgrade.new()
    subject_service:init()

    local fpga = fpga_service.init({}, {}, {})
    fpga.test_flag = "fpga object"

    local observer = subject_service.upgrade_observers["FPGA"]
    lu.assertIsTrue(observer.test_flag == "fpga object")

    local fpga_observer = subject_service.active_observers["FPGA"]
    lu.assertIsTrue(fpga_observer.test_flag == "fpga object")

    local parameters = {ComponentID = 23, ComponentIDEx = 165}
    local ok = pcall(function ()
        return subject_service:on_upgrade_prepare(_, 1, 'FPGA', '/dev/shm/upgrade/123456/name', parameters)
    end)
    lu.assertIsTrue(ok == true)

    fructl.get_chassis_power_status = function ()
        return "ON"
    end

    local ok2 = pcall(function ()
        return subject_service:on_upgrade_process(_, 1, 'FPGA', '/dev/shm/upgrade/123456/name', parameters)
    end)
    lu.assertIsTrue(ok2 == true)
    local ok3 = pcall(function ()
        return subject_service:on_active_process(_, 1, 'FPGA')
    end)
    lu.assertIsTrue(ok3 == true)
end

function TestUpgradeSubject:test_build_firmware_type_map()
    utils.get_firmware_uid = function()
        return true
    end
    cfg.is_hpc_vrd_pkg = function()
        return true
    end

    local subject_service = upgrade.new()
    subject_service:init()

    local parameters = {ComponentID = 23, ComponentIDEx = 115}
    local res = subject_service:build_firmware_type_map('Mcu', '/dev/shm/upgrade/123456/name', parameters)
    lu.assertEquals(res, 'DPUMcu')
    local parameters = {ComponentID = 23, ComponentIDEx = 105}
    local res1 = subject_service:build_firmware_type_map('Vrd', '/dev/shm/upgrade/123456/name', parameters)
    lu.assertEquals(res1, 'HPCVrd')
end

function TestUpgradeSubject:test_cpld_test_firmware_type()
    local old_load_file = ini_parse.load_file
    ini_parse.load_file = function (arg) return {EquipmentTest = {TestCase = 'cpld'}} end
    local subject_service = upgrade.new()
    subject_service:init()
    subject_service:cpld_test_firmware_type('test', nil)
    local ret = subject_service.firmware_parsers['test']()
    lu.assertEquals(ret, 'cpld_test')
    ini_parse.load_file = old_load_file
end