-- 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 test_ipmi = {}
local bs = require('mc.bitstring')
local log = require('mc.logging')
local test_storage_common = require('test_storage_common')
require('ipmi')
local MANUFACTURE_ID <const> = 0x0007DB

local function send_ipmi(data)
    return test_storage_common.send_ipmi(data)
end

local IPMI_GET_RSP = '<<ManufactureId:3/unit:8, Reserve:1/unit:8, Data/string>>'
local IPMI_SET_RSP = '<<ManufactureId:3/unit:8, Reserve:4/unit:8, Data/string>>'
local IPMI_SIMPLE_RSP = '<<ManufactureId:3/unit:8>>'

function test_ipmi.get_hdd_pwr_status()
    log:notice('================ test get_hdd_pwr_status ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x62 0x00 0x00 0x01 0x0')
    if ok then
        local data = bs.new(IPMI_GET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.get_controller_list()
    log:notice('================ test get_controller_list ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3d 0x00 0x00 0xFF 0xFF 0xFF 0x00 0x00 0x05')
    if ok then
        local data = bs.new(IPMI_GET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.get_controller_fw_version()
    log:notice('================ test get_controller_fw_version ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3d 0x00 0x01 0x00 0xFF 0xFF 0x00 0x00 0x05')
    if ok then
        local data = bs.new(IPMI_GET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.get_controller_nvdata_version()
    log:notice('================ test get_controller_nvdata_version ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3d 0x00 0x02 0x00 0xFF 0xFF 0x00 0x00 0x05')
    if ok then
        local data = bs.new(IPMI_GET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.get_controller_info()
    log:notice('================ test get_controller_info ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3d 0x00 0x03 0x01 0xFF 0xFF 0x00 0x00 0x05')
    if ok then
        local data = bs.new(IPMI_GET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.get_logical_drive_list()
    log:notice('================ test get_logical_drive_list ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3d 0x00 0x04 0x00 0xFF 0xFF 0x00 0x00 0x05')
    if ok then
        local data = bs.new(IPMI_GET_RSP):unpack(rsp)
        if data then
            assert(data.ManufactureId == MANUFACTURE_ID)
        end
    end
end

function test_ipmi.get_controller_pds()
    log:notice('================ test get_controller_pds ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3d 0x00 0x08 0x00 0xFF 0xFF 0x00 0x00 0x05')
    if ok then
        local data = bs.new(IPMI_GET_RSP):unpack(rsp)
        if data then
            assert(data.ManufactureId == MANUFACTURE_ID)
        end
    end
end

function test_ipmi.get_physical_drive_location()
    log:notice('================ test get_physical_drive_location ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3d 0x00 0x09 0xFF 0x01 0xFF 0x00 0x00 0x05')
    if ok then
        local data = bs.new(IPMI_GET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.get_physical_drive_info()
    log:notice('================ test get_physical_drive_info ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3d 0x00 0x0A 0xFF 0x01 0xFF 0x00 0x00 0x05')
    if ok then
        local data = bs.new(IPMI_GET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.get_physical_drive_led_status()
    log:notice('================ test get_physical_drive_led_status ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3d 0x00 0x12 0xFF 0x00 0xFF 0x00 0x00 0x05')
    if ok then
        local data = bs.new(IPMI_GET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.get_array_list()
    log:notice('================ test get_array_list ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3d 0x00 0x0B 0x00 0xFF 0xFF 0x00 0x00 0x05')
    if ok then
        local data = bs.new(IPMI_GET_RSP):unpack(rsp)
        if data then
            assert(data.ManufactureId == MANUFACTURE_ID)
        end
    end
end

function test_ipmi.get_array_lds()
    log:notice('================ test get_array_lds ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3d 0x00 0x0D 0x01 0x00 0x00 0x00 0x00 0x05')
    if ok then
        local data = bs.new(IPMI_GET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.get_array_pds()
    log:notice('================ test get_array_pds ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3d 0x00 0x0E 0x01 0x00 0x00 0x00 0x00 0x05')
    if ok then
        local data = bs.new(IPMI_GET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.get_logical_drive_list_ex()
    log:notice('================ test get_logical_drive_list_ex ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3d 0x00 0x13 0x00 0xFF 0xFF 0x00 0x00 0x05')
    if ok then
        local data = bs.new(IPMI_GET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
        assert(data.Data == '')
    end
end

function test_ipmi.get_array_lds_ex()
    log:notice('================ test get_array_lds_ex ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3d 0x00 0x15 0x01 0x00 0x00 0x00 0x00 0x05')
    if ok then
        local data = bs.new(IPMI_GET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

-- 条件限制
-- WritingLength后面有几个Byte,WritingLength就要填几
-- Data部分是由所有相关参数拼接而成,具体如下:
-- name,第一个字节表示长度,读取该字节指定的若干长度作为name, 如0x02 0x48 0x64 表示name为:'He'
-- 其他则是接口参数
function test_ipmi.create_logical_drive_on_new_array()
    log:notice('================ test create_logical_drive_on_new_array ================')
    local basic_info = '0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x01 0x00 0xFF 0xFF 0x00 0x00 0x00 '
    local data_len = '0x15 ' --WritingLength
    local name_info = '0x02 0x48 0x65 '
    local raid_type = '0x00 '
    local capacity = '0x64 0x00 0x00 0x00 ' --4byte,小端模式
    local capacity_unit = '0x00 '
    local strip_size = '0x09 '
    local read_policy = '0x01 '
    local write_policy = '0x01 '
    local io_policy = '0xFF '
    local access_policy = '0x00 '
    local drive_cache_policy = '0x00 '
    local initialization_mode = '0x00 '
    local span_number = '0x01 '
    local span_drive_number = '0x03 '
    local span_drive_id_list = '0x04 0x05 0x06'

    local merged_code = basic_info
        .. data_len
        .. name_info
        .. raid_type
        .. capacity
        .. capacity_unit
        .. strip_size
        .. read_policy
        .. write_policy
        .. io_policy
        .. access_policy
        .. drive_cache_policy
        .. initialization_mode
        .. span_number
        .. span_drive_number
        .. span_drive_id_list
    local ok, rsp = send_ipmi(merged_code)
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.create_logical_drive_on_existed_array()
    log:notice('================ test create_logical_drive_on_existed_array ================')
    local ok, rsp = send_ipmi(
        '0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x03 0x01 0x01 0x00 0x00 '
            .. '0x00 0x00 0x16 0x09 0x69 0x70 0x6d 0x69 0x63 0x72 0x65 0x61 0x74 0x64 0x00 0x00 0x00 '
            .. '0x01 0xff 0xff 0xff 0xff 0xff 0xff 0xff'
    )
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.delete_logical_drive()
    log:notice('================ test delete_logical_drive ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x04 0x01 0xFF 0xFF 0x00 0x00 0x00 0x01 0x01')
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.set_logic_drive_rp()
    log:notice('================ test set_logic_drive_rp ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x06 0x00 0x02 0xFF 0x00 0x00 0x00 0x01 0x01')
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.set_logic_drive_wp()
    log:notice('================ test set_logic_drive_wp ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x07 0x00 0x02 0xFF 0x00 0x00 0x00 0x01 0x01')
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
        assert(data.Data == '')
    end
end

function test_ipmi.set_logic_drive_bootable()
    log:notice('================ test set_logic_drive_bootable ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x0D 0x00 0x02 0xFF 0x00 0x00 0x00 0x01 0x01')
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.set_controller_copyback()
    log:notice('================ test set_controller_copyback ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x0E 0x00 0xFF 0xFF 0x00 0x00 0x00 0x01 0x01')
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
        assert(data.Data == '')
    end
end

function test_ipmi.set_controller_smarter_copyback()
    log:notice('================ test set_controller_smarter_copyback ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x0F 0x00 0xFF 0xFF 0x00 0x00 0x00 0x01 0x01')
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.set_controller_restore_settings()
    log:notice('================ test set_controller_restore_settings ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x10 0x00 0xFF 0xFF 0x00 0x00 0x00 0x01 0x01')
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
        assert(data.Data == '')
    end
end

function test_ipmi.set_controller_jbod()
    log:notice('================ test set_controller_jbod ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x14 0x00 0x02 0xFF 0x00 0x00 0x00 0x01 0x01')
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.set_location_indicator_state()
    log:notice('================ test set_location_indicator_state ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x11 0x00 0xFF 0xFF 0x00 0x00 0x00 0x01 0x01')
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.set_firmware_status()
    log:notice('================ test set_firmware_status ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x13 0x00 0x02 0xFF 0x00 0x00 0x00 0x01 0x06')
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
        assert(data.Data == '')
    end
end

function test_ipmi.set_hotspare_type()
    log:notice('================ test set_hotspare_type ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x12 0x00 0x02 0xFF 0x00 0x00 0x00 0x01 0x01 0x00')
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
        assert(data.Data == '')
    end
end

function test_ipmi.set_controller_outofband()
    log:notice('================ test set_controller_outofband ================')
    local ok
    local rsp
    ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x15 0x00 0xFF 0xFF 0x00 0x00 0x00 0x01 0x00')
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        if not data then
            return
        end
        assert(data.ManufactureId == MANUFACTURE_ID)
        assert(data.Data == '')
    end
    ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x15 0x00 0xFF 0xFF 0x00 0x00 0x00 0x01 0x01')
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        if not data then
            return
        end
        assert(data.ManufactureId == MANUFACTURE_ID)
        assert(data.Data == '')
    end
    ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x15 0x00 0xFF 0xFF 0x00 0x00 0x00 0x01 0x02')
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        if not data then
            return
        end
        assert(data.ManufactureId == MANUFACTURE_ID)
        assert(data.Data == '')
    end
    ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x15 0x00 0xFF 0xFF 0x00 0x00 0x00 0x01 0x03')
    if ok then
        local data = bs.new(IPMI_SET_RSP):unpack(rsp)
        if not data then
            return
        end
        assert(data.ManufactureId == MANUFACTURE_ID)
        assert(data.Data == '')
    end
end

function test_ipmi.set_raid_fault_status()
    log:notice('================ test set_raid_fault_status ================')
    local ok
    local rsp
    ok, rsp = send_ipmi('0x30 0x92 0xdb 0x07 0x00 0x05 0x0E 0x00 0x00 0x00 0x00 0x00 0x45')
    if ok then
        local data = bs.new(IPMI_SIMPLE_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.set_pd_log_collect()
    log:notice('================ test set_pd_log_collect ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3d 0x00 0x18')
    if ok then
        local data = bs.new(IPMI_SIMPLE_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

function test_ipmi.set_fault_indicator_state()
    log:notice('================ test set_pd_log_collect ================')
    local ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x18 0xff 0x00 0xff 0x00 0x00 0x02 0x00 0x01')
    if ok then
        local data = bs.new(IPMI_SIMPLE_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

return test_ipmi