-- 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 bs = require 'mc.bitstring'
local utils = require 'mc.utils'
local lu = require 'luaunit'
local log = require 'mc.logging'
local vrd_object = require 'vrd.vrd_object'
local vrd_manager = require 'vrd.vrd_manager'
local ipmi = require 'ipmi'
local enums = require 'ipmi.enums'
local vrd_enums = require 'vrd.enum.vrd_enums'
local client = require 'general_hardware.client'

local channel_type = enums.ChannelType
local comp_code = ipmi.types.Cc

TestVrdManager = {}

function TestVrdManager:test_parse_vrd_rsp_info()
    local payload = '\x00\x07\xDB' .. '\x01' .. -- CpuId
    '\x02\x09' .. -- PowerNum和InfoSize
    '\x00\x00' .. -- type和dieid
    '\x02\x03' .. -- 电压
    '\x04\x05\x06' .. -- 电流
    '\x07\x08' .. -- 温度
    '\x01\x02' .. -- type和dieid
    '\x05\x03' .. -- 电压
    '\x04\x05\x06' .. -- 电流
    '\x02\x06' -- 温度

    local obj = vrd_object.new()
    local cc = obj:parse_vrd_rsp_info(payload)
    assert(cc == comp_code.Success)

    payload = '\x00\x07\xDB' .. '\x01' .. -- CpuId
    '\x03\x09' .. -- PowerNum和InfoSize
    '\x00\x00' .. -- type和dieid
    '\x02\x03' .. -- 电压
    '\x04\x05\x06' .. -- 电流
    '\x07\x08' .. -- 温度
    '\x01\x02' .. -- type和dieid
    '\x05\x03' .. -- 电压
    '\x04\x05\x06' .. -- 电流
    '\x02\x06' .. -- 温度
    '\x02\x00' --   type和dieid

    cc = obj:parse_vrd_rsp_info(payload)
    assert(cc == comp_code.ResponseError)

end

function TestVrdManager:test_parse_with_real_data()
    local payload = table.concat({
        '\x00\x07\xDB\x00\x07\x09\x00\x01\x64\x01\xFF\xFF\xFF\xB4\x0C\x00',
        '\x03\x64\x01\xFF\xFF\xFF\xB4\x0C\x01\xFF\x64\x01\xFF\xFF\xFF\xB4',
        '\x0C\x02\xFF\x64\x01\xFF\xFF\xFF\xB4\x0C\x03\x00\x64\x01\xFF\xFF',
        '\xFF\xB4\x0C\x03\x02\x64\x01\xFF\xFF\xFF\xB4\x0C\x04\xFF\x64\x01', '\xFF\xFF\xFF\xB4\x0C'
    })

    local obj = vrd_object.new()
    local cc = obj:parse_vrd_rsp_info(payload)
    assert(cc == comp_code.Success)

    local payload = table.concat({
        '\x00\x07\xDB\x01\x07\x09\x00\x01\x64\x01\xF4\x00\x00\xB4\x0C\x00',
        '\x03\x64\x01\xF4\x00\x00\xB4\x0C\x01\xFF\x64\x01\xF4\x00\x00\xB4',
        '\x0C\x02\xFF\x64\x01\xF4\x00\x00\xB4\x0C\x03\x00\x64\x01\xF4\x00',
        '\x00\xB4\x0C\x03\x02\x64\x01\xF4\x00\x00\xB4\x0C\x04\xFF\x64\x01', '\xF4\x00\x00\xB4\x0C'
    })
    local cc = obj:parse_vrd_rsp_info(payload)
    assert(cc == comp_code.Success)
end

function TestVrdManager:test_set_vrd_to_invalid()
    local obj = vrd_object.new({})
    client.GetSmBiosObjects = function ()
        return {{ SmbiosStatus = 3}}
    end
    obj:set_vrd_to_invalid()
    assert(obj.vrd.VrdTemperatureCelsius == 0x7EFF)
end

function TestVrdManager:test_reset_vrd_info()
    local manager_obj = vrd_manager.new()
    local vrd_obj = vrd_object.new()
    vrd_obj.vrd = { SystemId = 1, Cpu0v9TACore = 10, Cpu0v75DDRVDD = 10, Cpu0v9TBCore = 10, Cpu0v9Uncore = 10, Cpu0v8NADVDD = 10, Cpu0v8NBDVDD = 10, Cpu1v1DDRVddq = 10,
        CpuTACoreTemp = 0, CpuDDRVDDTemp = 0, CpuTBCoreTemp = 0, CpuUncoreTemp = 0, CpuNADVDDTemp = 0, CpuNBDVDDTemp = 0, CpuDDRVddqTemp = 0, VrdTemperatureCelsius = 0,
        Status = 1, retry = 0}
    manager_obj.vrd_collection[1] = vrd_obj
    manager_obj.vrd_mgmt_table[1] = { mds_obj = { SystemId = 1, Status = 1, CpuId = 0},
    reset_vrd_info = function ()
        return
    end}
    local ok = pcall(function ()
        manager_obj:reset_vrd_info(1)
    end)
    lu.assertEquals(ok, true)
end

-- 测试用例：温度变化更新
function TestVrdManager:test_vrd_temp_update()
    local obj = vrd_object.new({
        CpuTACoreTemp = 50,
        CpuDDRVDDTemp = 50,
        CpuTBCoreTemp = 50,
        CpuUncoreTemp = 50
    })

    obj.temperature_info_table[vrd_enums.POWER_TYPE.CORE + 1] = {}
    obj.temperature_info_table[vrd_enums.POWER_TYPE.CORE + 1][vrd_enums.POWER_DIEID.TA + 1] = 52.5  -- 变化2.5度
    obj.temperature_info_table[vrd_enums.POWER_TYPE.CORE + 1][vrd_enums.POWER_DIEID.TB + 1] = 53    -- 变化3度
    obj.temperature_info_table[vrd_enums.POWER_TYPE.DDR + 1] = {}
    obj.temperature_info_table[vrd_enums.POWER_TYPE.DDR + 1][vrd_enums.POWER_DIEID.NOT_EXIST + 1] = 47  -- 变化3度
    obj.temperature_info_table[vrd_enums.POWER_TYPE.UNCORE + 1] = {}
    obj.temperature_info_table[vrd_enums.POWER_TYPE.UNCORE + 1][vrd_enums.POWER_DIEID.NOT_EXIST + 1] = 55  -- 变化5度

    obj:update_vrd_temp()

    lu.assertEquals(obj.vrd.CpuTACoreTemp, 52.5)
    lu.assertEquals(obj.vrd.CpuTBCoreTemp, 53)
    lu.assertEquals(obj.vrd.CpuDDRVDDTemp, 47)
    lu.assertEquals(obj.vrd.CpuUncoreTemp, 55)
end