-- 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 chassis_service = require 'chassis_service'
local chassis_object = require 'chassis_object'
local client = require 'chassis.client'
local factory = require 'factory'

TestChassisIntrusion = {}

function TestChassisIntrusion:test_update_intrusion_status()
    local service = chassis_service.new()
    local obj = {
        Name = "1",
        IntrusionACOn = 0,
        IntrusionACOff = 0,
        CoverStatus = 0,
        IntrusionClear = 0,
        IntrusionFlag = 0,
        LastIntrusionACOn = 0,
        ['bmc.kepler.Chassis'] = {
            ['enable_shm_prop_cache'] = function (...)
            end
        }
    }
    service:add_object(obj)
    service:update_intrusion_status()
    lu.assertEquals(obj.IntrusionFlag, 0)
    lu.assertEquals(obj.LastIntrusionACOn, 0)

    obj.IntrusionACOff = 1
    service:update_intrusion_status()
    lu.assertEquals(obj.IntrusionFlag, 0)
    lu.assertEquals(obj.LastIntrusionACOn, 0)

    obj.IntrusionACOff = 0
    obj.IntrusionACOn = 1
    obj.CoverStatus = 1
    obj.IntrusionFlag = 0
    service:update_intrusion_status()
    lu.assertEquals(obj.IntrusionFlag, 1)
    lu.assertEquals(obj.LastIntrusionACOn, 1)

    obj.IntrusionACOff = 0
    obj.IntrusionACOn = 1
    obj.CoverStatus = 0
    obj.IntrusionFlag = 0
    service:update_intrusion_status()
    lu.assertEquals(obj.IntrusionFlag, 0)
    lu.assertEquals(obj.LastIntrusionACOn, 0)
end

function TestChassisIntrusion:test_get_chassis_status()
    local fructrl_obj = {
        PowerOnStrategy = 'AlwaysPowerOn',
        PowerState      = 'ON',
        PowerCtrlFault  = 0,
        LastPowerEvent  = 16
    }
    client.ForeachFruCtrlObjects = function (self, cb)
        cb(fructrl_obj)
    end
    client.GetFruCtrlObjects = function (self)
        return {
            [1] = {
                extra_params = {
                    SystemId = 1
                },
                PowerOnStrategy = fructrl_obj.PowerOnStrategy,
                PowerState = fructrl_obj.PowerState,
                PowerCtrlFault = fructrl_obj.PowerCtrlFault,
                LastPowerEvent = fructrl_obj.LastPowerEvent,
                PanelPowerButtonEnabled = true
            }
        }
    end
    local one_power_status = {
        Health = 0
    }
    client.ForeachStatusObjects = function (self, cb)
        cb(one_power_status)
    end
    local fan_obj = {
        FanHealth = 0
    }
    client.ForeachFanObjects = function (self, cb)
        cb(fan_obj)
    end
    local drive_status_obj = {
        Health = 0
    }
    client.ForeachDriveStatusObjects = function (self, cb)
        cb(drive_status_obj)
    end
    factory:register('led_service', {
        uid_obj = {
            uidled_info = {
                State = 0
            }
        }
    })
    factory:register('chassis_service', {
        chassis_collection = {
            {
                ChassisType = 0
            }
        }
    })

    -- 上电恢复策略 AlwaysPowerOn
    local ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.CurrentPowerState & 0x60, 0x40)

    -- 上电恢复策略 AlwaysPowerOff
    fructrl_obj.PowerOnStrategy = 'AlwaysPowerOff'
    ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.CurrentPowerState & 0x60, 0x00)

    -- 上电恢复策略 LastState
    fructrl_obj.PowerOnStrategy = 'LastState'
    ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.CurrentPowerState & 0x60, 0x20)

    -- 上电恢复策略 Unknown
    fructrl_obj.PowerOnStrategy = 'Unknown'
    ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.CurrentPowerState & 0x60, 0x60)

    -- 上电状态 ON
    ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.CurrentPowerState & 0x01, 1)

    -- 上电状态 OFF
    fructrl_obj.PowerState = 'OFF'
    ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.CurrentPowerState & 0x01, 0)

    -- UID 关闭
    ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.MiscChassisState & 0x70, 0x40)

    -- UID 闪烁
    local uid_obj = factory.led_service.uid_obj.uidled_info
    uid_obj.State = 5
    ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.MiscChassisState & 0x70, 0x50)

    -- UID 开启
    uid_obj.State = 255
    ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.MiscChassisState & 0x70, 0x60)

    -- 风扇状态 正常
    ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.MiscChassisState & 0x08, 0)

    -- 风扇状态 异常
    fan_obj.FanHealth = 1
    ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.MiscChassisState & 0x08, 0x08)

    -- 硬盘状态 正常
    ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.MiscChassisState & 0x04, 0)

    -- 硬盘状态 异常
    drive_status_obj.Health = 1
    ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.MiscChassisState & 0x04, 0x04)

    -- 未发生电源故障
    ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.CurrentPowerState & 0x10, 0)

    -- 发生电源故障
    fructrl_obj.PowerCtrlFault = 1
    ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.CurrentPowerState & 0x10, 0x10)

    -- 通过ipmi上电
    ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.LastPowerEvent, 0x10)

    -- 未通过ipmi上电
    fructrl_obj.LastPowerEvent = 0
    ret_val = chassis_service:ipmi_get_power_status(nil, {})
    lu.assertEquals(ret_val.LastPowerEvent, 0)

end