-- 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_util = require 'util.base_util'
local db_util = require 'util.db_util'
local bios_service = require 'service.bios_service'
local boot_service = require 'service.boot_service'
local boot_option_service = require 'service.boot_options_service'
local bios_factory = require 'factory.bios_factory'
local effective_time_handler = require 'handler.effective_time_handler'
local mode_handler = require 'handler.mode_handler'
local start_option_handler = require 'handler.start_option_handler'
local boot_def = require 'macros.boot_def'
local boot_flag = require 'pojo.boot.boot_flag'
local boot_valid = require 'pojo.boot.boot_valid'
local boot_option_object = require 'pojo.boot_options_object'
local obj_def = require 'macros.object_def'
local ipmi = require 'ipmi'
local base_messages = require 'messages.base'
local custom_messages = require 'messages.custom'
local comp_code = ipmi.types.Cc
local open_db = require 'bios.db'
local boot_config_activate_service = require 'service.boot_config_activate_service'
local KmcClient = require 'service.kmc_client'
local crypt = require 'utils.crypt'
local lu = require 'luaunit'
local signal = require 'interface.signal'
local pro_global = require 'macros.property_global'
local project_dir = os.getenv('PROJECT_DIR')

local test_common = require 'test_common.utils'
local smbios_object = require 'pojo.smbios_object'
local bus = test_common.dbus_launch('../.dbus', nil, true)

test_mode_ipmi = {}

local function construct_ctx()
    local ctx = {}
    ctx.ChanType = 1
    ctx.get_initiator = function()
        return {}
    end

    return ctx
end

local function save_func()
end

function test_mode_ipmi:test_bean()
    local option_db_obj = {}
    option_db_obj.BootFlags = '/0/0/3/4/5'
    option_db_obj.ValidFlag = '/0/0/0/0/0/0/7/8/9/10/11/12/13/14/15/16'
    option_db_obj.save = save_func

    local boot_db_obj = {}
    boot_db_obj.BootSourceOverrideMode = 'UEFI'
    boot_db_obj.BootOrder = '/HardDiskDrive/PXE/DVDROMDrive/Others'
    boot_db_obj.save = save_func

    local bios_ser = bios_service.get_instance(bus)
    local boot_ser = boot_service.get_instance(boot_db_obj)
    local boot_option_ser = boot_option_service.get_instance(option_db_obj)

    bios_factory.register_bean('bios_service', bios_ser)
    bios_factory.register_bean('boot_service', boot_ser)
    bios_factory.register_bean('boot_option_service', boot_option_ser)

    bios_ser:set_bios_prop('CurrentValueFileName', project_dir .. '/test/test_data/currentvalue.json')
    bios_ser:set_bios_prop('ResultFileName', project_dir .. '/test/test_data/result.json')
    os.execute('touch ../test_data/setting2.json')
    bios_ser:set_bios_prop('SettingFileName', project_dir .. '/test/test_data/setting2.json')
    bios_ser:set_bios_prop('RegistryFileName', project_dir .. '/test/test_data/registry.json')
end

function test_mode_ipmi:test_z_clear()
    local bios_ser = bios_service.get_instance(bus)

    os.execute('rm -rf ../test_data/setting2.json')
    bios_ser:set_bios_prop('CurrentValueFileName', '/data/opt/currentvalue.json')
    bios_ser:set_bios_prop('ResultFileName', '/data/opt/result.json')
    bios_ser:set_bios_prop('SettingFileName', '/data/opt/setting.json')
    bios_ser:set_bios_prop('RegistryFileName', '/data/opt/registry.json')
end

function test_mode_ipmi:test_effective_time_handler()
    local effective_none_handler = effective_time_handler.effective_none_handler.new()
    assert(effective_none_handler ~= nil)

    local res = effective_none_handler.handle()
    assert(res == false)

    local data = {}
    res = effective_none_handler.handle(data)
    assert(res == false)

    data[1] = 1
    res = effective_none_handler.handle(data)
    assert(res == false)

    data[0] = 0x40
    res = effective_none_handler.handle(data)
    assert(res == true)
    assert(data[0] == 0x40)

    data[0] = 0
    local effective_once_handler = effective_time_handler.effective_once_handler.new()
    assert(effective_once_handler ~= nil)
    res = effective_once_handler.handle(data)
    assert(res == true)
    assert(data[0] == 0x80)

    data[0] = 0
    local effective_forever_handler = effective_time_handler.effective_forever_handler.new()
    assert(effective_forever_handler ~= nil)
    res = effective_forever_handler.handle(data)
    assert(res == true)
    assert(data[0] == 0xc0)
end

function test_mode_ipmi:test_mode_handler_handler()
    local legacy_handler = mode_handler.legacy_handler.new()
    assert(legacy_handler ~= nil)

    local data = {}
    local res = legacy_handler.handle(data)
    assert(res == false)

    data[0] = 0
    res = legacy_handler.handle(data)
    assert(res == true)
    assert(data[0] == 0)

    local uefi_handler = mode_handler.uefi_handler.new()
    assert(uefi_handler ~= nil)

    data[0] = 0
    res = uefi_handler.handle(data)
    assert(res == true)
    assert(data[0] == 0x20)
end

function test_mode_ipmi:test_start_option_handler()
    local option_handler = start_option_handler.option_handler.new()
    assert(option_handler ~= nil)

    local res = option_handler.handle()
    assert(res == false)

    local data = {}
    data[1] = 0
    res = option_handler.handle(data, boot_def.NO_OVERRIDE)
    assert(res == true)
    assert(data[1] == 0)

    data[1] = 0
    res = option_handler.handle(data, boot_def.FORCE_CD_DVD)
    assert(res == true)
    assert(data[1] == 0x14)

    data[1] = 0
    res = option_handler.handle(data, boot_def.FORCE_FLOPPY_REMOVABLE_MEDIA)
    assert(res == true)
    assert(data[1] == 0x3C)
end

function test_mode_ipmi:test_util()
    local tbl = {}
    tbl[0] = 1
    tbl[6] = 2
    local len = bs_util.cal_table_len(tbl)
    assert(len == 2)

    local data
    data = db_util.decode_db_info('/1/128/3/4/5')
    assert(data[0] == 1)
    assert(data[1] == 128)
    assert(data[2] == 3)
    assert(data[4] == 5)

    local db_info = db_util.encode_db_info(data)
    assert(db_info == '/1/128/3/4/5')

    data = db_util.decode_db_info('/HardDiskDrive/PXE/DVDROMDrive/Others', 1, true)
    assert(data[1] == 'HardDiskDrive')
    assert(data[2] == 'PXE')
    assert(data[3] == 'DVDROMDrive')
    assert(data[4] == 'Others')

    db_info = db_util.encode_db_info(data, 1)
    assert(db_info == '/HardDiskDrive/PXE/DVDROMDrive/Others')
end

function test_mode_ipmi:test_boot_flag()
    local boot_flag_cfg = boot_flag.new()
    assert(boot_flag_cfg ~= nil)

    local enable = boot_flag_cfg:get_bmc_enable()
    assert(enable == boot_def.BMC_ENABLE)

    local option_db_obj = {}
    option_db_obj.BootFlags = '/1/128/3/4/5'
    boot_flag_cfg = boot_flag.new(option_db_obj)
    assert(boot_flag_cfg ~= nil)
    enable = boot_flag_cfg:get_bmc_enable()
    assert(enable == boot_def.BMC_DISABLE)

    option_db_obj.BootFlags = '/0/0/3/4/5'
    option_db_obj.save = save_func
    option_db_obj.ValidFlag = '/0/0/0/0/0/0/7/8/9/10/11/12/13/14/15/16'
    local boot_option_ser = boot_option_service.get_instance(option_db_obj)
    bios_factory.register_bean('boot_options_service', boot_option_ser)
    boot_flag_cfg = boot_flag.new(option_db_obj)
    assert(boot_flag_cfg ~= nil)
    enable = boot_flag_cfg:get_bmc_enable()
    assert(enable == boot_def.BMC_ENABLE)

    local res = boot_flag_cfg:set_boot_mode(6)
    assert(res == false)
    res = boot_flag_cfg:set_boot_mode(boot_def.BIOS_BOOT_LEGACY)
    local data = boot_flag_cfg:get_info()
    assert(res == true)
    assert(data[0] == 0x80)

    res = boot_flag_cfg:set_boot_mode(boot_def.BIOS_BOOT_UEFI)
    data = boot_flag_cfg:get_info()
    assert(res == true)
    assert(data[0] == 0xA0)

    res = boot_flag_cfg:set_effective_time(boot_def.EFFECTIVE_ONCE)
    data = boot_flag_cfg:get_info()
    assert(res == true)
    assert(data[0] == 0xA0)

    res = boot_flag_cfg:set_effective_time(boot_def.EFFECTIVE_FOREVER)
    data = boot_flag_cfg:get_info()
    assert(res == true)
    assert(data[0] == 0xE0)

    res = boot_flag_cfg:set_start_option(boot_def.FORCE_PEX, boot_def.EFFECTIVE_ONCE)
    data = boot_flag_cfg:get_info()
    assert(res == true)
    assert(data[1] == 0x04)

    res = boot_flag_cfg:set_start_option(boot_def.FORCE_FLOPPY_REMOVABLE_MEDIA,
        boot_def.EFFECTIVE_ONCE)
    data = boot_flag_cfg:get_info()
    assert(res == true)
    assert(data[1] == 0x3C)
end

function test_mode_ipmi:test_boot_valid()
    local boot_valid_cfg = boot_valid.new()
    assert(boot_valid_cfg ~= nil)

    local option_db_obj = {}
    option_db_obj.ValidFlag = '/0/0/0/0/0/0/7/8/9/10/11/12/13/14/15/16'
    option_db_obj.save = save_func

    boot_valid_cfg = boot_valid.new(option_db_obj)
    assert(boot_valid_cfg ~= nil)

    local res = boot_valid_cfg:update_db_info()
    assert(res == true)

    boot_valid_cfg:set_boot_option_valid(boot_def.BIOS_BOOT_FLAGS_CMD,
        boot_def.BIOS_BOOT_OPTION_VALID)
    boot_valid_cfg:set_boot_option_valid(boot_def.BIOS_BOOT_PARTITION_SCAN_CMD,
        boot_def.BIOS_BOOT_OPTION_VALID)
    boot_valid_cfg:set_boot_option_valid(boot_def.BIOS_BOOT_INITIATOR_MAILBOX_CMD,
        boot_def.BIOS_BOOT_OPTION_VALID)
    local valid = boot_valid_cfg:get_boot_option_valid(boot_def.BIOS_BOOT_FLAGS_CMD)
    assert(valid == boot_def.BIOS_BOOT_OPTION_VALID)
    valid = boot_valid_cfg:get_boot_option_valid(boot_def.BIOS_BOOT_INITIATOR_MAILBOX_CMD)
    assert(valid == boot_def.BIOS_BOOT_OPTION_VALID)

    boot_valid_cfg:set_boot_option_valid(boot_def.BIOS_BOOT_INITIATOR_MAILBOX_CMD,
        boot_def.BIOS_BOOT_OPTION_INVALID)
    valid = boot_valid_cfg:get_boot_option_valid(boot_def.BIOS_BOOT_INITIATOR_MAILBOX_CMD)
    assert(valid == boot_def.BIOS_BOOT_OPTION_INVALID)

    valid = boot_valid_cfg:get_boot_option_valid(boot_def.BIOS_BOOT_FLAGS_CMD)
    assert(valid == boot_def.BIOS_BOOT_OPTION_VALID)
    valid = boot_valid_cfg:get_boot_option_valid(boot_def.BIOS_BOOT_PARTITION_SCAN_CMD)
    assert(valid == boot_def.BIOS_BOOT_OPTION_VALID)
end

local function construct_db()
    local ok, datas = pcall(require, 'bios.datas')
    if not ok then
        -- 如果没有datas配置，证明当前组件不需要datas，仅打开数据库
        datas = nil
    end
    local db = open_db(':memory:', datas)
    return db
end

function test_mode_ipmi:test_boot_option_object()
    local option_db_obj = {}
    option_db_obj.BootFlags = '/0/0/3/4/5'
    option_db_obj.ValidFlag = '/0/0/0/0/0/0/7/8/9/10/11/12/13/14/15/16'
    option_db_obj.save = save_func
    local boot_option_obj = boot_option_object.new({SystemId = 1}, construct_db())
    assert(boot_option_obj ~= nil)

    local boot_flag_cfg = boot_option_obj:get_cfg_function(boot_def.BIOS_BOOT_FLAGS_CMD)
    assert(boot_flag_cfg ~= nil)

    local boot_valid_cfg = boot_option_obj:get_cfg_function(boot_def.BIOS_BOOT_NUM)
    assert(boot_valid_cfg ~= nil)

    local boot_write_cfg = boot_option_obj:get_cfg_function(boot_def.BIOS_BOOT_OEM_WRITE_PROT_CMD)
    assert(boot_write_cfg == nil)

    local res = boot_option_obj:set_boot_mode(boot_def.BIOS_BOOT_LEGACY)
    assert(res == true)

    res = boot_option_obj:set_boot_mode(boot_def.BIOS_BOOT_UEFI)
    assert(res == true)

    res = boot_option_obj:set_boot_mode(5)
    assert(res == false)

    boot_option_obj:set_boot_option_valid(boot_def.BIOS_BOOT_FLAGS_CMD,
        boot_def.BIOS_BOOT_OPTION_VALID)
    boot_option_obj:set_boot_option_valid(boot_def.BIOS_BOOT_PARTITION_SCAN_CMD,
        boot_def.BIOS_BOOT_OPTION_VALID)
    boot_option_obj:set_boot_option_valid(boot_def.BIOS_BOOT_INITIATOR_MAILBOX_CMD,
        boot_def.BIOS_BOOT_OPTION_VALID)
    local valid = boot_option_obj:get_boot_option_valid(boot_def.BIOS_BOOT_FLAGS_CMD)
    assert(valid == boot_def.BIOS_BOOT_OPTION_VALID)

    boot_option_obj:set_boot_option_valid(boot_def.BIOS_BOOT_INITIATOR_MAILBOX_CMD,
        boot_def.BIOS_BOOT_OPTION_INVALID)
    valid = boot_option_obj:get_boot_option_valid(boot_def.BIOS_BOOT_INITIATOR_MAILBOX_CMD)
    assert(valid == boot_def.BIOS_BOOT_OPTION_INVALID)

    res = boot_option_obj:set_effective_time(boot_def.EFFECTIVE_ONCE)
    local data = boot_flag_cfg:get_info()
    assert(res == true)
    assert(data[0] == 0xA0)

    res = boot_option_obj:set_effective_time(boot_def.EFFECTIVE_FOREVER)
    data = boot_flag_cfg:get_info()
    assert(res == true)
    assert(data[0] == 0xE0)

    local info = boot_option_obj:get_option_info(boot_def.BIOS_BOOT_FLAGS_CMD)
    assert(info ~= nil)
    assert(#info == 4)
end

local function test_order(boot_ser, ctx)
    local res = boot_ser:set_boot_priority(ctx, '{"BootTypeOrder0":"Others",' ..
    '"BootTypeOrder1":"PXE",' ..
    '"BootTypeOrder2":"DVDROMDrive",' ..
    '"BootTypeOrder3":"HardDiskDrive"}')
    local order_data = boot_ser:get_boot_prop('BootOrder')
    assert(order_data[1] == 'Others')
    assert(order_data[2] == 'PXE')
    assert(order_data[3] == 'DVDROMDrive')
    assert(order_data[4] == 'HardDiskDrive')
    assert(res == 0)
end

function test_mode_ipmi:test_boot_service_order()
    local ctx = construct_ctx()
    local boot_ser = boot_service.get_instance()
    assert(boot_ser ~= nil)

    boot_ser:set_boot_prop('BootModeSupport', true)
    local res = boot_ser:get_boot_prop('BootModeSupport')
    assert(res == true)
    boot_ser:set_boot_prop('BootModeSupport', false)
    res = boot_ser:get_boot_prop('BootModeSupport')
    assert(res == false)
    boot_ser:set_boot_prop('BootModeSupport', true)

    local _, res = pcall(function()
        return boot_ser:set_boot_priority(ctx, '{"BootTypeOrder0":"PXE",' ..
                                                '"BootTypeOrder1":"HardDiskDrive",' ..
                                                '"BootTypeOrder2":"PXE",' ..
                                                '"BootTypeOrder3":"Others"}')
    end)
    assert(res.name == custom_messages.PropertyItemDuplicateMessage.Name)

    _, res = pcall(function()
        return boot_ser:set_boot_priority(ctx, '{"BootTypeOrder0":"DVDROMDrive",' ..
                                                '"BootTypeOrder0":"HardDiskDrive",' ..
                                                '"BootTypeOrder0":"PXE",' ..
                                                '"BootTypeOrder0":"Others"}')
    end)
    assert(res.name == custom_messages.WrongArrayLengthMessage.Name)

    _, res = pcall(function()
        return boot_ser:set_boot_priority(ctx, '{"BootTypeOrder0":"DVDROMDrive",' ..
                                                '"BootTypeOrder1":"a",' ..
                                                '"BootTypeOrder2":"PXE",' ..
                                                '"BootTypeOrder3":"Others"}')
    end)
    assert(res.name == custom_messages.PropertyItemNotInListMessage.Name)

    res = boot_ser:set_boot_priority(ctx, '{"BootTypeOrder0":"DVDROMDrive",' ..
                                           '"BootTypeOrder1":"HardDiskDrive",' ..
                                           '"BootTypeOrder2":"PXE",' ..
                                           '"BootTypeOrder3":"Others"}')
    local order_data = boot_ser:get_boot_prop('BootOrder')
    assert(order_data[1] == 'DVDROMDrive')
    assert(order_data[2] == 'HardDiskDrive')
    assert(order_data[3] == 'PXE')
    assert(order_data[4] == 'Others')
    assert(res == 0)

    test_order(boot_ser, ctx)
end

function test_mode_ipmi:test_boot_service_start_option_flag()
    local boot_ser = boot_service.get_instance()
    assert(boot_ser ~= nil)

    local res = boot_ser:set_start_option_flag(6)
    assert(res == false)

    res = boot_ser:set_start_option_flag(boot_def.EFFECTIVE_NONE)
    assert(res == true)
    local option_flag = boot_ser:get_boot_prop(obj_def.BOOT_SOURCE_OVERRIDE_ENABLED)
    assert(option_flag == 'Disabled')

    res = boot_ser:set_start_option_flag(boot_def.EFFECTIVE_ONCE)
    assert(res == true)
    option_flag = boot_ser:get_boot_prop(obj_def.BOOT_SOURCE_OVERRIDE_ENABLED)
    assert(option_flag == 'Once')

    res = boot_ser:set_start_option_flag(boot_def.EFFECTIVE_FOREVER)
    assert(res == true)
    option_flag = boot_ser:get_boot_prop(obj_def.BOOT_SOURCE_OVERRIDE_ENABLED)
    assert(option_flag == 'Continuous')
end

function test_mode_ipmi:test_boot_service_start_option()
    local boot_ser = boot_service.get_instance()
    assert(boot_ser ~= nil)

    local res = boot_ser:set_boot_options_property(boot_def.BMC_DISABLE, 9)
    assert(res == false)

    res = boot_ser:set_boot_options_property(boot_def.BMC_DISABLE, boot_def.NO_OVERRIDE)
    local option_flag = boot_ser:get_boot_prop(obj_def.BOOT_SOURCE_OVERRIDE_ENABLED)
    local option = boot_ser:get_boot_prop(obj_def.BOOT_SOURCE_OVERRIDE_TARGET)
    assert(res == true)
    assert(option_flag == 'Disabled')
    assert(option == 'None')

    res = boot_ser:set_boot_options_property(boot_def.BMC_ENABLE, boot_def.FORCE_BIOS_SETUP)
    option_flag = boot_ser:get_boot_prop(obj_def.BOOT_SOURCE_OVERRIDE_ENABLED)
    option = boot_ser:get_boot_prop(obj_def.BOOT_SOURCE_OVERRIDE_TARGET)
    assert(res == true)
    assert(option_flag == 'Disabled')
    assert(option == 'BiosSetup')
end

function test_mode_ipmi:test_boot_option_service_mode()
    local boot_option_ser = boot_option_service.get_instance()
    local boot_ser = boot_service.get_instance()
    assert(boot_option_ser ~= nil)
    assert(boot_ser ~= nil)

    local res = boot_option_ser:set_start_option_flag(construct_ctx(), boot_def.EFFECTIVE_FOREVER, 1)
    local option_flag = boot_ser:get_boot_prop(obj_def.BOOT_SOURCE_OVERRIDE_ENABLED)
    local boot_flag_data = boot_option_ser:get_option_info(boot_def.BIOS_BOOT_FLAGS_CMD, 1)
    assert(boot_flag_data[0] == 0xE0)
    assert(res == 0)
    assert(option_flag == 'Continuous')

    res = boot_option_ser:set_start_option(construct_ctx(), boot_def.FORCE_BIOS_SETUP)
    boot_flag_data = boot_option_ser:get_option_info(boot_def.BIOS_BOOT_FLAGS_CMD)
    assert(res == 0)
    assert(boot_flag_data[1] == 0x18)

    res = boot_option_ser:set_boot_mode(construct_ctx(), boot_def.BIOS_BOOT_UEFI)
    boot_flag_data = boot_option_ser:get_option_info(boot_def.BIOS_BOOT_FLAGS_CMD)
    assert(res == 0)
    assert(boot_flag_data[0] == 0xE0)

    local _, res = pcall(function()
        return boot_option_ser:set_boot_mode(construct_ctx(), boot_def.BIOS_BOOT_LEGACY)
    end)
    boot_flag_data = boot_option_ser:get_option_info(boot_def.BIOS_BOOT_FLAGS_CMD)
    assert(res.name == base_messages.InternalErrorMessage.Name)
    assert(boot_flag_data[0] == 0xE0)
end

function test_mode_ipmi:test_get_boot_option()
    local boot_option_ser = boot_option_service.get_instance()
    assert(boot_option_ser ~= nil)

    local res = boot_option_ser:get_boot_option_data()
    assert(res.CompletionCode == comp_code.InvalidFieldRequest)

    local req = {}
    req.BootOptionSelector = boot_def.BIOS_BOOT_FLAGS_CMD
    req.OtherSelector = '0'
    res = boot_option_ser:get_boot_option_data(req)
    assert(res.CompletionCode == comp_code.ReqDataLenInvalid)

    req.OtherSelector = '00'
    res = boot_option_ser:get_boot_option_data(req)
    assert(res.CompletionCode == comp_code.Success)
    local str = res.OtherData
    assert(str ~= nil)

    local boot_ser = boot_service.get_instance()
    local mode = boot_ser:get_boot_prop(obj_def.BOOT_SOURCE_OVERRIDE_MODE)
    assert(mode == "UEFI")
end

function test_mode_ipmi:test_update_boot_mode_setting_json_error()
    bs_util.get_file_json = function ()
        return nil
    end
    local boot_option_ser = boot_option_service.get_instance()
    boot_option_ser:update_boot_mode(nil, 1)
end

function test_mode_ipmi:test_update_boot_mode_mode_str_error()
    local option_db_obj = {}
    option_db_obj.BootFlags = '/0/0/3/4/5'
    option_db_obj.ValidFlag = '/0/0/0/0/0/0/7/8/9/10/11/12/13/14/15/16'
    local boot_option_ser = boot_option_service.get_instance()
    boot_def.BIOS_BOOT_TYPE_STR = "test"
    boot_option_ser:update_boot_mode(option_db_obj, 1)
end

function test_mode_ipmi:test_decrypt_password_error()
    local boot_option_ser = boot_config_activate_service.get_instance()
    boot_option_ser.count_down_task = nil
    boot_option_ser:on_power_state_changed()
    local tem = crypt.convert_string_to_ciphertext
    crypt.convert_string_to_ciphertext = function ()
        return nil
    end
    KmcClient.decrypt_password("test")
    crypt.convert_string_to_ciphertext = tem
end

function test_mode_ipmi:test_get_smbios_info_table()
    local smbios_obj = {}
    local db = {}
    db.SmBiosInfoTable = {}
    db.SmBiosInfoTable.Id = {eq = function()
        return {}
    end}
    local smbios_first = {first = function ()
        return {SmBiosUpdatedFlag = nil, save = function()

        end}
    end}
    db.select = function (t)
        return {where = function(t)
            return smbios_first
        end}
    end

    smbios_object.new(db, 2, smbios_obj)
end

function test_mode_ipmi:test_clear_cmos_taskdown()
    local bios_ser = bios_factory.get_service('bios_service')
    bios_ser:create_countdown_task(construct_ctx())
    local ok = bios_ser:task_running()
    lu.assertEquals(ok, true)
    bios_ser:on_power_state_changed()
    ok = bios_ser:task_running()
    if not ok then
        ok = false
    end
    lu.assertEquals(ok, false)
end

function test_mode_ipmi:test_set_option_taskdown()
    local boot_options_ser = bios_factory.get_service('boot_options_service')
    boot_options_ser:create_option_countdown_task(construct_ctx(), 'Pxe')
    boot_options_ser.StartOption = 'Pxe'
    local ok = boot_options_ser:option_task_running()
    lu.assertEquals(ok, true)
    boot_options_ser:on_option_power_state_changed()
    ok = boot_options_ser:option_task_running()
    if not ok then
        ok = false
    end
    lu.assertEquals(ok, false)
end

function test_mode_ipmi:test_set_effective_time_taskdown()
    local boot_options_ser = bios_factory.get_service('boot_options_service')
    boot_options_ser:create_times_countdown_task(construct_ctx(), 'Once')
    boot_options_ser.StartOptionFlag = 'Once'
    local ok = boot_options_ser:times_task_running()
    lu.assertEquals(ok, true)
    boot_options_ser:on_times_power_state_changed()
    ok = boot_options_ser:times_task_running()
    if not ok then
        ok = false
    end
    lu.assertEquals(ok, false)
end

function test_mode_ipmi:test_power_state_changed()
    pro_global.G_SET_BIOS_OPTION_FLAG = 1
    pro_global.G_SET_BIOS_OPTION = 1
    signal.power_state_changed_callback()
    lu.assertEquals(pro_global.G_SET_BIOS_OPTION_FLAG, 0)
    lu.assertEquals(pro_global.G_SET_BIOS_OPTION, 0)
    pro_global.G_SET_BIOS_OPTION_FLAG = 1
    pro_global.G_SET_BIOS_OPTION = 2
    signal.power_state_changed_callback()
    lu.assertEquals(pro_global.G_SET_BIOS_OPTION_FLAG, 0)
    lu.assertEquals(pro_global.G_SET_BIOS_OPTION, 0)
    pro_global.G_SET_BIOS_OPTION_FLAG = 2
    pro_global.G_SET_BIOS_OPTION = 1
    signal.power_state_changed_callback()
    lu.assertEquals(pro_global.G_SET_BIOS_OPTION_FLAG, 0)
    lu.assertEquals(pro_global.G_SET_BIOS_OPTION, 0)
    pro_global.G_SET_BIOS_OPTION_FLAG = 2
    pro_global.G_SET_BIOS_OPTION = 2
    signal.power_state_changed_callback()
    lu.assertEquals(pro_global.G_SET_BIOS_OPTION_FLAG, 0)
    lu.assertEquals(pro_global.G_SET_BIOS_OPTION, 0)
    pro_global.G_SET_BIOS_OPTION_FLAG = 0
    pro_global.G_SET_BIOS_OPTION = 0
    signal.power_state_changed_callback()
    lu.assertEquals(pro_global.G_SET_BIOS_OPTION_FLAG, 0)
    lu.assertEquals(pro_global.G_SET_BIOS_OPTION, 0)
end