-- 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 c_ipmi_service = require 'ipmi_service'
local drive_collection = require 'drive.drive_collection'
local rpc_service_drive = require 'rpc_services.rpc_service_drive'
local c_drive = require 'drive.drive_object'
local common_def = require 'common_def'

TestSetSlotPowerState = {}

local function construct_ctx()
    local ctx = {}
    ctx.ChanType = 1
    ctx.get_initiator = function()
        return {}
    end
    return ctx
end

function TestSetSlotPowerState:test_rpc_service_drive()
    -- 未配置CSR
    local drive_1 = {RefControllerId = 255, SlotPowerState = 0,
        get_property_source = function()
            return {}
        end,
        set_slot_power_state_by_smc = function()
            return true
        end
    }
    local ok, _ = pcall(function()
        return rpc_service_drive.set_slot_power_state(drive_1, construct_ctx(), "ForceOn")
    end)
    lu.assertEquals(ok, false)

    ok, _ = pcall(function()
        return rpc_service_drive.set_slot_power_state(drive_1, construct_ctx(), "ForceOnn")
    end)
    lu.assertEquals(ok, false)

    -- 配置了CSR，CPLD支持硬盘上下电smc命令字
    local drive_2 = {RefControllerId = 255, SlotPowerState = 0,
        get_property_source = function()
            return {"xx"}
        end,
        set_slot_power_state_by_smc = function()
            return true
        end
    }
    ok, _ = pcall(function()
        return rpc_service_drive.set_slot_power_state(drive_2, construct_ctx(), "ForceOn")
    end)
    lu.assertEquals(ok, true)

    -- 配置了CSR，CPLD不支持硬盘上下电smc命令字
    local drive_2 = {RefControllerId = 255, SlotPowerState = 0,
        get_property_source = function()
            return {"xx"}
        end,
        set_slot_power_state_by_smc = function()
            return false
        end
    }
    ok, _ = pcall(function()
        return rpc_service_drive.set_slot_power_state(drive_2, construct_ctx(), "ForceOn")
    end)
    lu.assertEquals(ok, false)
end

function TestSetSlotPowerState:test_set_slot_power_state_ipmi()
    local req = {}
    req.ManufacturerId = 0xFFFFFF
    req.SetSelector = 255
    req.DriveId = 1
    drive_collection.get_drive_by_id = function(controller_id, drive_id)
        return {Name = "Disk0"}
    end
    local _, res = pcall(function()
        return c_ipmi_service.set_slot_power_state(req, construct_ctx())
    end)
    -- 测试ManufacturerId非法，返回错误
    lu.assertEquals(res.CompletionCode, 0xcc)

    req.ManufacturerId = 0x0007DB
    req.WritingLength = 1
    req.Data = 2
    local _, res = pcall(function()
        return c_ipmi_service.set_slot_power_state(req, construct_ctx())
    end)
    -- 测试 request data invalid，返回错误
    lu.assertEquals(res.CompletionCode, 0xc9)

    req.Data = 1
    drive_collection.get_drive_by_id = function()
        return nil
    end
    local _, res = pcall(function()
        return c_ipmi_service.set_slot_power_state(req, construct_ctx())
    end)
    -- IPMI get drive failed，返回错误
    lu.assertEquals(res.CompletionCode, 0xcc)

    drive_collection.get_drive_by_id = function()
        return {RefControllerId = 255, SlotPowerState = 0,
            set_slot_power_state_by_smc = function(num)
                return true
            end,
            get_property_source = function()
                return {}
            end
        }
    end
    local _, res = pcall(function()
        return c_ipmi_service.set_slot_power_state(req, construct_ctx())
    end)
    -- 未配置CSR，返回错误
    lu.assertEquals(res.CompletionCode, 0xd5)

    drive_collection.get_drive_by_id = function()
        return {RefControllerId = 255, SlotPowerState = 0,
            set_slot_power_state_by_smc = function(num)
                return false
            end,
            get_property_source = function()
                return {"xx"}
            end
        }
    end
    local _, res = pcall(function()
        return c_ipmi_service.set_slot_power_state(req, construct_ctx())
    end)
    -- 配置了CSR，smc不支持，返回错误
    lu.assertEquals(res.CompletionCode, 0xd6)

    drive_collection.get_drive_by_id = function()
        return {RefControllerId = 255, SlotPowerState = 0,
            set_slot_power_state_by_smc = function(num)
                return true
            end,
            get_property_source = function()
                return {"xx"}
            end
        }
    end
    local _, res = pcall(function()
        return c_ipmi_service.set_slot_power_state(req, construct_ctx())
    end)
    -- 配置了CSR，smc支持，返回正常
    lu.assertEquals(res.CompletionCode, 0)
end

function TestSetSlotPowerState:test_get_slot_power_state_ipmi()
    local req = {}
    req.ManufacturerId = 0xFFFFFF
    req.SetSelector = 255
    req.DriveId = 1
    drive_collection.get_drive_by_id = function(controller_id, drive_id)
        return {Name = "Disk0", Id = 1}
    end
    local _, res = pcall(function()
        return c_ipmi_service.get_slot_power_state(req, construct_ctx())
    end)
    -- 测试ManufacturerId非法，返回错误
    lu.assertEquals(res.CompletionCode, 0xcc)

    req.ManufacturerId = 0x0007DB
    req.ReadingLength = 1
    drive_collection.get_drive_by_id = function(controller_id, drive_id)
        return nil
    end
    local _, res = pcall(function()
        return c_ipmi_service.get_slot_power_state(req, construct_ctx())
    end)
    -- 测试 request data invalid，返回错误
    lu.assertEquals(res.CompletionCode, 0xcc)

    drive_collection.get_drive_by_id = function()
        return {RefControllerId = 255, SlotPowerState = 0}
    end
    local _, res = pcall(function()
        return c_ipmi_service.get_slot_power_state(req, construct_ctx())
    end)
    -- 测试，返回正常
    lu.assertEquals(res.CompletionCode, 0)
    lu.assertEquals(res.PowerState, 0)
end