-- 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 onepower = require 'device_tree.adapters.OnePower'

local PS_HEALTH_EVENT = {
    VOUT_STATUS = 0,
    IOUT_STATUS = 1,
    VIN_STATUS = 2,
    MFR_STATUS = 6
}

local TestOnePower = {}

local function build_stub(deep_sleep_enabled, mfr_status)
    local cleared = false
    local stub = {
        DeepSleepEnabled = deep_sleep_enabled,
        MfrSpecificStatus = mfr_status or 0,
        debounce = {
            health_event = {
                [PS_HEALTH_EVENT.MFR_STATUS] = {
                    clear_debounced_val = function()
                        cleared = true
                    end
                }
            }
        }
    }
    return stub, function()
        return cleared
    end
end

-- 场景1：深度休眠退出，检测Mfr状态清零并置255
function TestOnePower:test_set_resource_exit_deep_sleep()
    local stub, is_cleared = build_stub(1, 0)
    onepower.set_resource(stub, 'DeepSleepEnabled', 0)
    lu.assertTrue(is_cleared())
    lu.assertEquals(stub.MfrSpecificStatus, 255)
    lu.assertEquals(stub.DeepSleepEnabled, 0)
end

-- 场景2：非深度休眠状态下重复设置，无额外动作
function TestOnePower:test_set_resource_no_transition()
    local stub, is_cleared = build_stub(0, 123)
    onepower.set_resource(stub, 'DeepSleepEnabled', 0)
    lu.assertFalse(is_cleared())
    lu.assertEquals(stub.MfrSpecificStatus, 123)
    lu.assertEquals(stub.DeepSleepEnabled, 0)
end

-- 场景3：普通属性写入，不触发防抖逻辑
function TestOnePower:test_set_resource_other_property()
    local stub, is_cleared = build_stub(1, 0)
    onepower.set_resource(stub, 'OutputVoltage', 12.5)
    lu.assertFalse(is_cleared())
    lu.assertEquals(stub.OutputVoltage, 12.5)
end

local function make_debounce_return(val)
    return {
        get_debounced_val = function(_, input)
            return val ~= nil and val or input
        end
    }
end

-- 场景4：满足扩展条件时拉高0x7A bit4，并同步其他告警
function TestOnePower:test_check_input_output_fault_updates_voltage()
    local stub = {
        debounce = {
            health_event = {
                [PS_HEALTH_EVENT.IOUT_STATUS] = make_debounce_return(5),
                [PS_HEALTH_EVENT.VOUT_STATUS] = make_debounce_return(0),
                [PS_HEALTH_EVENT.VIN_STATUS] = make_debounce_return(7)
            },
            output_voltage_fault_extend = make_debounce_return(1)
        },
        InputState = 1,
        IsUpgrading = false,
        DeepSleepEnabled = 0,
        OutputState = 0,
        OutputVoltageFault = 0,
        OutputCurrentFault = 0,
        InputVoltageFault = 0
    }
    function stub:check_output_voltage_fault_extend_condition()
        return 1
    end
    local health_event = {
        output_voltage_fault = 0,
        output_current_fault = 0,
        input_voltage_fault = 0,
        mfr_specific_status = 64,
        temper_fault = 0,
        fan_fault = 0
    }
    onepower.check_input_output_fault(stub, health_event)
    lu.assertEquals(stub.OutputCurrentFault, 5)
    lu.assertEquals(stub.InputVoltageFault, 7)
    lu.assertEquals(stub.OutputVoltageFault, 16)
end

-- 场景5：缺少电压信息时保持原值，仅更新电流
function TestOnePower:test_check_input_output_fault_without_voltage_info()
    local stub = {
        debounce = {
            health_event = {
                [PS_HEALTH_EVENT.IOUT_STATUS] = make_debounce_return(2),
                [PS_HEALTH_EVENT.VOUT_STATUS] = make_debounce_return(nil)
            },
            output_voltage_fault_extend = make_debounce_return(nil)
        },
        OutputVoltageFault = 8,
        OutputCurrentFault = 0
    }
    local health_event = {
        output_current_fault = 4
    }
    onepower.check_input_output_fault(stub, health_event)
    lu.assertEquals(stub.OutputCurrentFault, 2)
    lu.assertEquals(stub.OutputVoltageFault, 8)
end

-- 场景6：扩展条件全部满足时返回1
function TestOnePower:test_check_output_voltage_fault_extend_condition_true()
    local stub = {
        InputState = 1,
        IsUpgrading = false,
        DeepSleepEnabled = 0,
        OutputState = 0
    }
    setmetatable(stub, { __index = onepower })
    local health_event = {
        mfr_specific_status = 64,
        output_current_fault = 0,
        input_voltage_fault = 0,
        temper_fault = 0,
        fan_fault = 0,
        output_voltage_fault = 0
    }
    local ret = stub:check_output_voltage_fault_extend_condition(health_event)
    lu.assertEquals(ret, 1)
end

local function build_extend_stub()
    local stub = {
        InputState = 1,
        IsUpgrading = false,
        DeepSleepEnabled = 0,
        OutputState = 0
    }
    setmetatable(stub, { __index = onepower })
    local base_event = {
        mfr_specific_status = 64,
        output_current_fault = 0,
        input_voltage_fault = 0,
        temper_fault = 0,
        fan_fault = 0,
        output_voltage_fault = 0
    }
    return stub, base_event
end

-- 场景7：输入状态异常时返回0
function TestOnePower:test_extend_condition_input_state()
    local stub, event = build_extend_stub()
    stub.InputState = 0
    lu.assertEquals(stub:check_output_voltage_fault_extend_condition(event), 0)
end

-- 场景8：升级状态中返回0
function TestOnePower:test_extend_condition_is_upgrading()
    local stub, event = build_extend_stub()
    stub.IsUpgrading = true
    lu.assertEquals(stub:check_output_voltage_fault_extend_condition(event), 0)
end

-- 场景9：深度休眠模式返回0
function TestOnePower:test_extend_condition_deep_sleep()
    local stub, event = build_extend_stub()
    stub.DeepSleepEnabled = 1
    lu.assertEquals(stub:check_output_voltage_fault_extend_condition(event), 0)
end

-- 场景10：输出状态非0返回0
function TestOnePower:test_extend_condition_output_state()
    local stub, event = build_extend_stub()
    stub.OutputState = 1
    lu.assertEquals(stub:check_output_voltage_fault_extend_condition(event), 0)
end

-- 场景11：mfr_specific_status未命中返回0
function TestOnePower:test_extend_condition_mfr_status()
    local stub, event = build_extend_stub()
    event.mfr_specific_status = 0
    lu.assertEquals(stub:check_output_voltage_fault_extend_condition(event), 0)
end

-- 场景12：存在输出电流故障返回0
function TestOnePower:test_extend_condition_output_current_fault()
    local stub, event = build_extend_stub()
    event.output_current_fault = 1
    lu.assertEquals(stub:check_output_voltage_fault_extend_condition(event), 0)
end

-- 场景13：存在输入电压故障返回0
function TestOnePower:test_extend_condition_input_voltage_fault()
    local stub, event = build_extend_stub()
    event.input_voltage_fault = 1
    lu.assertEquals(stub:check_output_voltage_fault_extend_condition(event), 0)
end

-- 场景14：存在过温故障返回0
function TestOnePower:test_extend_condition_temper_fault()
    local stub, event = build_extend_stub()
    event.temper_fault = 1
    lu.assertEquals(stub:check_output_voltage_fault_extend_condition(event), 0)
end

-- 场景15：存在风扇故障返回0
function TestOnePower:test_extend_condition_fan_fault()
    local stub, event = build_extend_stub()
    event.fan_fault = 1
    lu.assertEquals(stub:check_output_voltage_fault_extend_condition(event), 0)
end

-- 场景16：output_voltage_fault本身为1时返回0
function TestOnePower:test_extend_condition_output_voltage_fault()
    local stub, event = build_extend_stub()
    event.output_voltage_fault = 1
    lu.assertEquals(stub:check_output_voltage_fault_extend_condition(event), 0)
end

return TestOnePower

