-- 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_write_bios = {}
local bs = require 'mc.bitstring'
require 'ipmi'
local test_bios_common = require 'test_bios_common'

local WRITE_BIOS_DATA_RSP = '<<ManufactureId:3/unit:8, RequiredOffset/string>>'

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

function test_write_bios.test_send_invalid()
    local ok = send_ipmi('0x30 0x92 0xdb 0x07 0x00 0x09 0x09 0x1c 0x02 0x00 0x10 0x00 0x00 0x00')
    assert(ok == false)

    ok = send_ipmi('0x30 0x92 0xdb 0x06 0x00 0x00 0x09 0x00 0x1c 0x02 0x00 0x10 0x00 0x00 0x00')
    assert(ok == false)
end

function test_write_bios.test_send_prepare()
    local ok, rsp = send_ipmi('0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1a 0x00 0x00 0x00 0x00 0x10 0x00')
    assert(ok == true)
    if ok then
        local data = bs.new(WRITE_BIOS_DATA_RSP):unpack(rsp)
        assert(data.ManufactureId == 0x0007DB)
        assert(data.RequiredOffset == '')
    end

    ok, rsp = send_ipmi('0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1c 0x00 0x00 0x00 0x00 0x10 0x00')
    assert(ok == true)
    if ok then
        local data = bs.new(WRITE_BIOS_DATA_RSP):unpack(rsp)
        assert(data.ManufactureId == 0x0007DB)
        assert(data.RequiredOffset == '')
    end

    ok = send_ipmi('0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1c 0x00 0x00 0x00 0x00 0x00 0x10')
    assert(ok == false)

    ok = send_ipmi('0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x04 0x00 0x00 0x66 0x12 0x21 0x10')
    assert(ok == false)
end

-- 准备测试专用路径
function test_write_bios.test_send_default()
    local ok = send_ipmi('0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1c 0x02 0x00 0x10 0x00 0x00 0x00')
    assert(ok == false)

    ok = send_ipmi('0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x04 0x05 0x00 0x10 0x00 0x00 0x00')
    assert(ok == false)
end

local function string_to_binary(data)
    local res = ''
    for i = 1, #data do
        local c = string.sub(data, i, i)
        local byte = string.format('%x', string.byte(c))
        res = res .. ' 0x' .. byte
    end

    return res
end

function test_write_bios.test_send_data()
    local ok, rsp = send_ipmi('0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1a 0x00 0x00 0x00 0x00 0x10 0x00')
    assert(ok == true)
    if ok then
        local data = bs.new(WRITE_BIOS_DATA_RSP):unpack(rsp)
        assert(data.ManufactureId == 0x0007DB)
        assert(data.RequiredOffset == '')
    end

    ok = send_ipmi("0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1a 0x01 0x51")
    assert(ok == false)

    ok = send_ipmi("0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1a 0x01 0x51 0x00 0x00 0x00 0x00")
    assert(ok == false)

    local json_data = string_to_binary('{ "Messages": [ ], "Time": "2044-01-13T10:56:46+00:00" }')
    ok = send_ipmi("0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1a 0x01 0x51 0x00 0x00 0x00 0x01" .. json_data)
    assert(ok == false)

    json_data = string_to_binary('{ "Messages": [ ], "Time": "2044-01-13T10:56:46+00:00" }')
    ok = send_ipmi("0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1a 0x01 0x52 0x00 0x00 0x00 0x00" .. json_data)
    assert(ok == false)

    json_data = string_to_binary('{ "Messages": [ ], "Time": "2044-01-13T10:56:46+00:00" }')
    ok, rsp = send_ipmi("0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1a 0x01 0xAF 0x00 0x00 0x00 0x00" .. json_data)
    assert(ok == true)
    if ok then
        local data = bs.new(WRITE_BIOS_DATA_RSP):unpack(rsp)
        assert(data.ManufactureId == 0x0007DB)
        assert(data.RequiredOffset == '')
    end
end

local function send_prepare_data()
    local ok, rsp = send_ipmi('0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1a 0x00 0x00 0x00 0x00 0x10 0x00')
    assert(ok == true)
    if ok then
        local data = bs.new(WRITE_BIOS_DATA_RSP):unpack(rsp)
        assert(data.ManufactureId == 0x0007DB)
        assert(data.RequiredOffset == '')
    end

    local json_data = string_to_binary('{ "Messages": [ ], "Time": "2044-01-13T10:56:46+00:00" }')
    ok, rsp = send_ipmi("0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1a 0x01 0xAF 0x00 0x00 0x00 0x00" .. json_data)
    assert(ok == true)
    if ok then
        local data = bs.new(WRITE_BIOS_DATA_RSP):unpack(rsp)
        assert(data.ManufactureId == 0x0007DB)
        assert(data.RequiredOffset == '')
    end
end

function test_write_bios.test_send_finish()
    -- 测试file_selector非法
    local ok = send_ipmi("0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x03 0x03 0x51")
    assert(ok == false)

    ok = send_ipmi("0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x9d 0x03 0x51")
    assert(ok == false)

    -- 测试没有chksum
    ok = send_ipmi("0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1a 0x03")
    assert(ok == false)

    -- 测试没有data_buf
    ok = send_ipmi("0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1a 0x03 0x51")
    assert(ok == false)

    -- 测试非法chksum
    send_prepare_data()
    ok = send_ipmi("0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1a 0x03 0x52")
    assert(ok == false)

    -- 测试写入display.ini
    send_prepare_data()
    ok = send_ipmi("0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x00 0x03 0x51")
    assert(ok == false)
end

function test_write_bios.test_send_current()
    -- 测试写入currentValue.json
    send_prepare_data()
    local ok, rsp = send_ipmi("0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1a 0x03 0xAF")
    assert(ok == true)
    if ok then
        local data = bs.new(WRITE_BIOS_DATA_RSP):unpack(rsp)
        assert(data.ManufactureId == 0x0007DB)
        assert(data.RequiredOffset == '')
    end
end

function test_write_bios.test_send_result()
    -- 测试写入result.json
    send_prepare_data()
    local ok, rsp = send_ipmi("0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1c 0x03 0xAF")
    assert(ok == true)
    if ok then
        local data = bs.new(WRITE_BIOS_DATA_RSP):unpack(rsp)
        assert(data.ManufactureId == 0x0007DB)
        assert(data.RequiredOffset == '')
    end
end

function test_write_bios.test_send_registry()
    -- 测试写入registry.json
    send_prepare_data()
    local ok, rsp = send_ipmi("0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x19 0x03 0xAF")
    assert(ok == true)
    if ok then
        local data = bs.new(WRITE_BIOS_DATA_RSP):unpack(rsp)
        assert(data.ManufactureId == 0x0007DB)
        assert(data.RequiredOffset == '')
    end
end

function test_write_bios.test_send_setting()
    -- 测试写入setting.json
    send_prepare_data()
    local ok, rsp = send_ipmi("0x30 0x92 0xdb 0x07 0x00 0x09 0x00 0x1b 0x03 0xAF")
    assert(ok == true)
    if ok then
        local data = bs.new(WRITE_BIOS_DATA_RSP):unpack(rsp)
        assert(data.ManufactureId == 0x0007DB)
        assert(data.RequiredOffset == '')
    end
end

function test_write_bios.test_send_file()
    test_write_bios.test_send_current()
    test_write_bios.test_send_result()
    test_write_bios.test_send_registry()
    test_write_bios.test_send_setting()
end

function test_write_bios.test_send_bios_data()
    test_write_bios.test_send_invalid()
    test_write_bios.test_send_default()
    test_write_bios.test_send_prepare()
    test_write_bios.test_send_data()
    test_write_bios.test_send_finish()
    test_write_bios.test_send_file()
end

return test_write_bios
