-- 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 ================')
    basic_info = '0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x01 0x00 0xFF 0xFF 0x00 0x00 0x00 '
    data_len = '0x15 ' --WritingLength
    name_info = '0x02 0x48 0x65 '
    raid_type = '0x00 '
    capacity = '0x64 0x00 0x00 0x00 ' --4byte，小端模式
    capacity_unit = '0x00 '
    strip_size = '0x09 '
    read_policy = '0x01 '
    write_policy = '0x01 '
    io_policy = '0xFF '
    access_policy = '0x00 '
    drive_cache_policy = '0x00 '
    initialization_mode = '0x00 '
    span_number = '0x01 '
    span_drive_number = '0x03 '
    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')
    assert(ok, true)
    local data = bs.new(IPMI_SET_RSP):unpack(rsp)
    if not data then
        return
    end
    assert(data.ManufactureId == MANUFACTURE_ID)
    assert(data.Data == '')
    ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x15 0x00 0xFF 0xFF 0x00 0x00 0x00 0x01 0x01')
    assert(ok, true)
    local data = bs.new(IPMI_SET_RSP):unpack(rsp)
    assert(data.ManufactureId == MANUFACTURE_ID)
    assert(data.Data == '')
    ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x15 0x00 0xFF 0xFF 0x00 0x00 0x00 0x01 0x02')
    assert(ok, true)
    local data = bs.new(IPMI_SET_RSP):unpack(rsp)
    assert(data.ManufactureId == MANUFACTURE_ID)
    assert(data.Data == '')
    ok, rsp = send_ipmi('0x30 0x93 0xdb 0x07 0x00 0x3e 0x00 0x15 0x00 0xFF 0xFF 0x00 0x00 0x00 0x01 0x03')
    assert(ok, true)
    local data = bs.new(IPMI_SET_RSP):unpack(rsp)
    assert(data.ManufactureId == MANUFACTURE_ID)
    assert(data.Data == '')
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')
    assert(ok, true)
    local data = bs.new(IPMI_SIMPLE_RSP):unpack(rsp)
    assert(data.ManufactureId == MANUFACTURE_ID)
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')
    assert(ok, true)
    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')
    assert(ok, true)
    if ok then
        local data = bs.new(IPMI_SIMPLE_RSP):unpack(rsp)
        assert(data.ManufactureId == MANUFACTURE_ID)
    end
end

return test_ipmi