-- 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 EXPretS 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 unit_manager = require 'unit_manager.unit_manager'
local common_ipmi = require 'common_ipmi'
local ipmi = require 'ipmi'
local cc = ipmi.types.Cc

TestCommonIpmi = {}

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

    return ctx
end

function TestCommonIpmi:test_set_device_action()
    local um = unit_manager.new()
    um.npu_boards = {
        {
            set_prop = function()
                return true
            end,
            get_prop = function()
                return 1
            end
        }
    }
    local req = { Slot = 0x0 }
    local ret = common_ipmi:set_device_action(req, construct_ctx())
    lu.assertEquals(ret.CompletionCode, cc.InvalidFieldRequest)

    req = { Slot = 0x1 }
    ret = common_ipmi:set_device_action(req, construct_ctx())
    lu.assertEquals(ret.CompletionCode, cc.Success)

    um = unit_manager.new()
    um.npu_boards = {
        {
            set_prop = function()
                return true
            end,
            get_prop = function()
                return 2
            end
        }
    }
    req = { Slot = 0x2 }
    ret = common_ipmi:set_device_action(req, construct_ctx())
    lu.assertEquals(ret.CompletionCode, cc.Success)

    um = unit_manager.new()
    um.npu_boards = {
        {
            set_prop = function()
                error('fail')
            end,
            get_prop = function()
                return 1
            end
        }
    }
    req = { Slot = 0x1 }
    ret = common_ipmi:set_device_action(req, construct_ctx())
    lu.assertEquals(ret.CompletionCode, cc.DataNotAvailable)
end

function TestCommonIpmi:test_reset_npuboard()
    local um = unit_manager.new()
    um.npu_boards = {
        {
            set_prop = function()
                return true
            end,
            get_prop = function()
                return 1
            end
        }
    }
    local req = {
        GroupId = 0xff, Lun = 0x0,
        Offset = 0x0, Length = 0x2,
        ComponentId = 0x1
    }
    local ret = common_ipmi:reset_npuboard(req, construct_ctx())
    lu.assertEquals(ret.CompletionCode, cc.InvalidFieldRequest)

    req.Length = 0x1
    ret = common_ipmi:reset_npuboard(req, construct_ctx())
    lu.assertEquals(ret.CompletionCode, cc.InvalidFieldRequest)

    req.Data = string.char(0xff, 0x01)
    ret = common_ipmi:reset_npuboard(req, construct_ctx())
    lu.assertEquals(ret.CompletionCode, cc.InvalidFieldRequest)

    req.ComponentId = 0x0
    req.Data = string.char(0xff)
    ret = common_ipmi:reset_npuboard(req, construct_ctx())
    lu.assertEquals(ret.CompletionCode, cc.InvalidFieldRequest)

    req.ComponentId = 0x1
    ret = common_ipmi:reset_npuboard(req, construct_ctx())
    lu.assertEquals(ret.CompletionCode, cc.InvalidFieldRequest)

    um.npu_boards = {
        {
            set_prop = function()
                error('set fail')
            end,
            get_prop = function()
                return 2
            end
        }
    }
    req.ComponentId = 0x2
    req.Data = string.char(0xff)
    ret = common_ipmi:reset_npuboard(req, construct_ctx())
    lu.assertEquals(ret.CompletionCode, cc.DataNotAvailable)

    um.npu_boards = {
        {
            set_prop = (function()
                local cnt = 0
                return function()
                    cnt = cnt + 1
                    if cnt == 3 then
                        error('set fail')
                    end
                    return true
                end
            end)(),
            get_prop = function()
                return 2
            end
        }
    }
    req.ComponentId = 0x2
    req.Data = string.char(0xff)
    ret = common_ipmi:reset_npuboard(req, construct_ctx())
    lu.assertEquals(ret.CompletionCode, cc.DataNotAvailable)

    um.npu_boards = {
        {
            set_prop = function()
                return true
            end,
            get_prop = function()
                return 2
            end
        }
    }
    req.ComponentId = 0x2
    req.Data = string.char(0x0)
    ret = common_ipmi:reset_npuboard(req, construct_ctx())
    lu.assertEquals(ret.CompletionCode, cc.InvalidFieldRequest)

    req.ComponentId = 0x2
    req.Data = string.char(0xff)
    ret = common_ipmi:reset_npuboard(req, construct_ctx())
    lu.assertEquals(ret.CompletionCode, cc.Success)

    req.ComponentId = 0x2
    req.Data = string.char(0x1)
    ret = common_ipmi:reset_npuboard(req, construct_ctx())
    lu.assertEquals(ret.CompletionCode, cc.Success)
end
