-- 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_pcie_card = require 'device.class.pcie_card'
local ipmi = require 'ipmi'

TestPcieCard = {}

local PCIECARD_INTERFACE <const> = 'bmc.kepler.Systems.PCIeDevices.PCIeCard'

function TestPcieCard:test_set_prop()
    c_pcie_card.mds = {
        LocalProp = 1,
        SameProp = 1,
        [PCIECARD_INTERFACE] = {
            InfProp = 1,
            SameProp = 2
        }
    }
    lu.assertEquals(c_pcie_card:get_prop('SameProp'), 1)
    lu.assertEquals(c_pcie_card:get_prop('SameProp', PCIECARD_INTERFACE), 2)
    lu.assertEquals(c_pcie_card:get_prop('LocalProp'), 1)
    lu.assertEquals(c_pcie_card:get_prop('InfProp', PCIECARD_INTERFACE), 1)
    -- 如果本地属性中不存在，从默认Interface属性中查找
    lu.assertEquals(c_pcie_card:get_prop('InfProp'), 1)

    c_pcie_card:set_prop('SameProp', 10)
    lu.assertEquals(c_pcie_card:get_prop('SameProp'), 10)
    lu.assertEquals(c_pcie_card:get_prop('SameProp', PCIECARD_INTERFACE), 2)
    c_pcie_card:set_prop('SameProp', 11, PCIECARD_INTERFACE)
    lu.assertEquals(c_pcie_card:get_prop('SameProp'), 10)
    lu.assertEquals(c_pcie_card:get_prop('SameProp', PCIECARD_INTERFACE), 11)
    c_pcie_card:set_prop('LocalProp', 12)
    lu.assertEquals(c_pcie_card:get_prop('LocalProp'), 12)
    c_pcie_card:set_prop('InfProp', 13, PCIECARD_INTERFACE)
    lu.assertEquals(c_pcie_card:get_prop('InfProp'), 13, PCIECARD_INTERFACE)
    -- 如果本地属性中不存在，从默认Interface属性中查找
    c_pcie_card:set_prop('InfProp', 14)
    lu.assertEquals(c_pcie_card:get_prop('InfProp'), 14)
    lu.assertEquals(c_pcie_card:get_prop('InfProp'), 14, PCIECARD_INTERFACE)
end

function TestPcieCard:test_pcie_get_capid_addr()
    local c_request = ipmi.request
    ipmi.request = function()
        return 0xff
    end
    local pcie_info = {
        is_local = 1,
        cpu_id = 1,
        address = 1,
        function_num = 1,
        device_num = 1,
        bus_num = 1,
        read_length = 4
    }
    local ok = c_pcie_card:pcie_get_capid_addr(pcie_info)
    ipmi.request = c_request
    lu.assertEquals(ok, nil)
end

function TestPcieCard:test_get_pcie_lang_info()
    local position = 'position'
    local mdb_obj = {
        PcbID = 1,
        PcbVersion = '',
        SerialNumber = '',
        PartNumber = '',
        CardForServers = {},
        LinkSpeed = '',
        LinkSpeedCapability = '',
        LinkWidth = '',
        LinkWidthAbility = '',
        Protocol = '',
        MaxFrameLen = '',
        RefChip = ''
    }
    local bus = {}
    local reset_local_db = {}
    local pcie_obj = c_pcie_card.new(mdb_obj, position, bus, reset_local_db)

    local c_pcie_get_capid_addr = c_pcie_card.pcie_get_capid_addr
    c_pcie_card.pcie_get_capid_addr = function()
        return false
    end
    local pcie_device_obj = {
        get_prop = function()
            return true
        end
    }
    local ok = pcie_obj:get_pcie_lang_info(pcie_device_obj)
    c_pcie_card.pcie_get_capid_addr = c_pcie_get_capid_addr
    lu.assertEquals(ok, 1)
end

function TestPcieCard:test_sync_info_to_card()
    local obj = c_pcie_card.new({
        LocalProp = 1,
        SameProp = 1,
        [PCIECARD_INTERFACE] = {
            InfProp = 1,
            SameProp = 2
        }
    }, "", {}, {})
    local pcie_device_obj = {}
    pcie_device_obj.mds = {}
    pcie_device_obj.mds.property_changed = {
        on = function (_, func_prop_changed)
            pcall(func_prop_changed, 'MultihostPresence', 1, {})
        end
    }
    pcie_device_obj.get_prop = function ()
        return ''
    end
    pcie_device_obj.set_prop = function ()
        return true
    end
    local ok = pcall(function ()
        obj:sync_info_to_card(pcie_device_obj)
    end)
    lu.assertEquals(ok, true)
end

function TestPcieCard:test_update_board_id()
    local pcie_addr_obj = {
        ['get_prop'] = function()
            return 'get'
        end,
        ['set_prop'] = function()
            return 'set'
        end
    }
    local pcie_card_obj = {
        ['set_prop'] = function()
            return 'set'
        end
    }
    local ret = c_pcie_card.update_vid_did(pcie_card_obj, pcie_addr_obj)
    lu.assertEquals(ret, nil)
    local ret = c_pcie_card.update_description(pcie_card_obj, "card")
    lu.assertEquals(ret, nil)
end

function TestPcieCard:test_check_count()
    c_pcie_card.check_count = 0
    c_pcie_card:add_check_count()
    local ret = c_pcie_card:need_check()
    lu.assertEquals(ret, true)

    c_pcie_card:add_check_count()
    c_pcie_card:add_check_count()
    ret = c_pcie_card:need_check()
    lu.assertEquals(ret, false)
end