-- 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 lu = require('luaunit')
local sml = require('sml')
local c_ctrl_info = require('sml.ctrl_info')
local c_pd_info = require('sml.pd_info')
local c_pd_sas_smart_info = require('sml.pd_sas_smart_info')
local c_ld_info = require('sml.ld_info')
local c_battery_info = require('sml.battery_info')
local pd_object = require('pd.pd_object')
local import_export_eng = require('handler.export_import_engine')
local controller_collection = require('controller.controller_collection')
local project_dir = os.getenv('PROJECT_DIR')
local file_sec = require('utils.file')
local utils = require('mc.utils')
local ipmi = require('ipmi_service')
local battery_collection = require('battery.battery_collection')
local c_controller = require('controller.controller_object')
local debounce = require('mc.debounce.debounce')
local common_def = require('common_def')
local c_storageconfig = require('storageconfig.storageconfig_object')
local c_ctrl_commu_loss_monitor = require('ctrl_commu_loss_monitor')

local function make_pd_info(test_data)
    return c_pd_info.new({
        model = test_data.pd_model,
        temperature = test_data.pd_temperature,
        coerced_size = test_data.pd_capacity,
        interface_type = test_data.pd_interface_type,
        device_speed = test_data.pd_device_speed,
        link_speed = test_data.pd_link_speed,
        media_type = test_data.pd_media_type,
        fw_state = test_data.pd_fw_status,
        serial_num = test_data.pd_sn,
        manufacturer = test_data.pd_manufacturer,
        power_on_hours = test_data.pd_ssd_power_on_hours,
        firmware_version = test_data.pd_fw_version,
        rotation_speed = test_data.pd_rotation_speed,
        block_size = test_data.pd_block_size,
        sas_addr1 = test_data.pd_sas_addr_1,
        sas_addr2 = test_data.pd_sas_addr_2,
        remnant_media_wearout = test_data.pd_ssd_lifeleft,
        prefail_count = test_data.pd_predictive_fail_count,
        media_err_count = test_data.pd_media_err_count,
        other_err_count = test_data.pd_other_err_count,
        proginfo = {
            patrol_state = test_data.pd_patrol_status,
            rebuild_state = test_data.pd_rebuild_state,
            rebuild_progress = test_data.pd_rebuild_progress,
        },
        power_state = test_data.pd_power_state,
        boot_priority = test_data.pd_boot_priority,
        hot_spare = test_data.pd_hot_spare,
        last_prefail_event_seq_num = test_data.pd_last_prefail_event_seq_num,
    })
end

local function make_pd_sas_smart_info(test_data)
    return c_pd_sas_smart_info.new({
        strip_temperature = test_data.strip_temperature,
        glist_len = test_data.glist_len,
        plist_len = test_data.plist_len,
        manufacture_data = test_data.manufacture_data,
        blocks_sent = test_data.blocks_sent,
        blocks_received = test_data.blocks_received,
        minutes_left = test_data.minutes_left,
    })
end

local function make_battery_info(test_data)
    return c_battery_info.new({
        bbu_warnig_info_reported = test_data.bbu_warnig_info_reported,
        present = test_data.present,
        temperature = test_data.temperature,
        type = test_data.type,
        pack_missing = test_data.pack_missing,
        voltage_low = test_data.voltage_low,
        temperature_high = test_data.temperature_high,
        replacepack = test_data.replacepack,
        learn_cycle_failed = test_data.learn_cycle_failed,
        learn_cycle_timeout = test_data.learn_cycle_timeout,
        predictive_failure = test_data.predictive_failure,
        remaining_capacity_low = test_data.remaining_capacity_low,
        no_space = test_data.no_space,
        failed = test_data.failed,
    })
end

local controller = {
    Id = 0,
    DevFunction = 1,
    SocketId = 1,
    DevDevice = 1,
    TypeId = 99,
    Segment = 1,
    SystemId = 1,
    DevBus = 1,
    Name = 'HI1880_SP686C_M_16i_2G',
    OOBSupport = 1,
    path = 'Controller_1_0001010102',
    CtrlOption1 = 2275649443,
    CtrlOption2 = 32647,
    CtrlOption3 = 0,
    get_children = function()
        return {}
    end,
}

local function add_controller(self)
    self.bus_monitor_service.on_os_state_changed:emit(true)
    -- 第一次是触发注册
    self.tasks:run_all_task()
    self.object_manager.mc:add_object('Controller', controller, 1)
    ---@diagnostic disable-next-line: duplicate-set-field
    sml.get_battery_info = function(...)
        return make_battery_info(self.test_battery_info)
    end
    ---@diagnostic disable-next-line: duplicate-set-field
    sml.get_ctrl_info = function()
        return c_ctrl_info.new(self.test_controller_data)
    end
    -- 第二次是触发更新
    self.tasks:run_all_task()
    -- 第二次是触发更新
    self.tasks:run_all_task()
    return self.controller_collection:get_by_controller_id(controller.Id)
end

-- 测试新增控制器对象
function TestStorage:test_controller_add_object()
    -- hook ctrl 用到的 sml 函数
    ---@diagnostic disable-next-line: duplicate-set-field
    sml.get_ctrl_sas_addr = function()
        return '0x1100'
    end
    -- 添加控制器对象
    local obj = add_controller(self)

    -- 检查控制器对象的信息
    lu.assertEquals(obj.ControllerName, 'MyName')
    lu.assertEquals(obj.TemperatureCelsius, 10)
    lu.assertEquals(obj.FirmwareVersion, '2.0.0')
    lu.assertEquals(obj.SupportedMode, { 'RAID', 'JBOD' })
    lu.assertEquals(obj.MemorySizeMiB, 512)
    lu.assertEquals(obj.PCIeLinkWidth, 'x16')
    lu.assertEquals(obj.DeviceInterface, 'SPI')
    lu.assertEquals(obj.SASAddr, '0x1100')
    lu.assertEquals(obj.SerialNumber, '23456')
    lu.assertEquals(obj.MaxStripSizeBytes, 1024)
    lu.assertEquals(obj.MinStripSizeBytes, 512)
    lu.assertEquals(obj.SupportedRAIDTypes, { 'RAID0' })
    lu.assertEquals(obj.NVDataVersion, '1.0.0.1')
    lu.assertEquals(obj.DDREccCount, 20)
    lu.assertEquals(obj.CachePinnedState, 1)
    lu.assertEquals(obj.MaintainPDFailHistrory, 1)
    lu.assertEquals(obj.JBODState, 255)
    lu.assertEquals(obj.CopyBackState, 0)
    lu.assertEquals(obj.SmarterCopyBackState, 0)
    lu.assertEquals(obj.HardwareRevision, 'V200')
    lu.assertEquals(obj.BootDevices, { 'None', 'None' })
    lu.assertEquals(obj.ConsistencyCheckState, 1)
    lu.assertEquals(obj.PeriodOfHours, 230)
    lu.assertEquals(obj.Rate, 'Medium')
    lu.assertEquals(obj.AutoRepairEnabled, 1)
    lu.assertEquals(obj.RunningStatus, 'On')
    lu.assertEquals(obj.TotalVolumeCounts, 10)
    lu.assertEquals(obj.CompletedVolumeCounts, 10)
    lu.assertEquals(obj.WorkMode, 'RAID')

    -- 删除受模块管理的对象
    self.object_manager.mc:del_object('Controller', controller, 1)
    self.tasks:run_all_task()
end

-- 测试OS下电时清除信息
function TestStorage:test_controller_close_os()
    local drive_info = {
        HddBackplaneStartSlot = 0,
        Presence = 1,
        RelativeSlot = 1,
        ObjectName = 'Drive1',
        LocateLed = 1,
        FaultLed = 0,
    }
    self.object_manager.mc:add_object('Drive', drive_info)
    -- hook drive 用到的 sml 函数
    local params = {}

    ---@diagnostic disable-next-line: duplicate-set-field
    sml.get_pd_info = function(...)
        params['get_pd_info'] = { ... } -- 启动任务更新 drive 信息
        return make_pd_info(self.test_pd_info)
    end
    ---@diagnostic disable-next-line: duplicate-set-field
    sml.get_pd_sas_smart_info = function(...)
        params['get_pd_sas_smart_info'] = { ... } -- 启动任务更新 drive 信息
        return make_pd_sas_smart_info(self.test_pd_sas_smart_info)
    end

    local obj = add_controller(self)

    local drive = self.drive_collection:get_drive(drive_info.Name)
    local pd = { controller_id = obj.Id, slot_num = 2, enclosure_id = 3, device_id = 1 }
    drive:identified(pd)
    self.tasks:run_all_task()

    -- 检查加载成功
    lu.assertEquals(drive.TemperatureCelsius, 255)

    -- OS下电
    self.bus_monitor_service.on_os_state_changed:emit(false)
    self.tasks:run_all_task()

    drive = self.drive_collection:get_drive(drive_info.Name)
    lu.assertEquals(obj.TemperatureCelsius, 255)
    lu.assertEquals(drive.TemperatureCelsius, 255)

    -- MCTP准备完成
    self.bus_monitor_service.on_os_state_changed:emit(true)
    self.tasks:run_all_task()
    lu.assertNotIsNil(self.mctp_service.m_mctp_collection)
    lu.assertEquals(obj.TemperatureCelsius, 10)

    -- 删除受模块管理的对象
    self.object_manager.mc:del_object('Controller', controller, 1)
    self.tasks:run_all_task()
end

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

    return ctx
end
local ctl_ctx = construct_ctx()

-- 测试设置回拷功能
function TestStorage:test_controller_set_copyback()
    local controller = add_controller(self)
    -- 设置回拷成功
    sml.ctrl_operation = function()
        return 0
    end
    local ctx = construct_ctx()
    local rpc_service_controller = self.rpc_service_controller
    local ret =
        pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetCopyBackState', controller.Id, ctx, 1)
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)

    -- 不支持带外管理
    controller.OOBSupport = 0
    ret = pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetCopyBackState', controller.Id, ctx, 1)
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.OOBSupport = 1

    -- 非法输入
    ret = pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetCopyBackState', controller.Id, ctx, 3)
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 重复设置
    ret = pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetCopyBackState', controller.Id, ctx, 0)
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)

    -- 正在工作中
    controller.is_working = true
    ret = pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetCopyBackState', controller.Id, ctx, 1)
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.is_working = false

    -- 设置回拷返回失败
    sml.ctrl_operation = function()
        return 4248
    end
    ret = pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetCopyBackState', controller.Id, ctx, 1)
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 删除受模块管理的对象
    self.object_manager.mc:del_object('Controller', controller, 1)
    self.tasks:run_all_task()
end

-- 测试打印controller私有属性
function TestStorage:test_get_controller_info()
    local controller = add_controller(self)
    local rpc_service_controller = self.rpc_service_controller
    controller.DevBus = 3
    controller.DevDevice = 6
    controller.DevFunction = 9
    controller.Eid = 7
    controller.Phyaddr = 10
    controller.CtrlOption1 = 2275649443
    controller.CtrlOption2 = 6571
    controller.CtrlOption3 = 32512
    controller.SlotId = 0

    local ret, details = pcall(rpc_service_controller.get_controller_info, controller.Id)
    lu.assertEquals(ret, true)
    lu.assertEquals(details.DevBus, '3')
    lu.assertEquals(details.DevDevice, '6')
    lu.assertEquals(details.DevFunction, '9')
    lu.assertEquals(details.Eid, '7')
    lu.assertEquals(details.Phyaddr, '10')
    lu.assertEquals(details.CtrlOption1, '2275649443')
    lu.assertEquals(details.CtrlOption2, '6571')
    lu.assertEquals(details.CtrlOption3, '32512')
    lu.assertEquals(details.SlotId, '0')
end

-- 测试设置Smart回拷功能
function TestStorage:test_controller_set_smart_copyback()
    local controller = add_controller(self)
    -- 设置回拷成功
    sml.ctrl_operation = function()
        return 0
    end
    local rpc_service_controller = self.rpc_service_controller
    local ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetSmarterCopyBackState',
        controller.Id,
        ctl_ctx,
        1
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)

    -- 不支持带外管理
    controller.OOBSupport = 0
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetSmarterCopyBackState',
        controller.Id,
        ctl_ctx,
        1
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.OOBSupport = 1

    -- 非法输入
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetSmarterCopyBackState',
        controller.Id,
        ctl_ctx,
        3
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 重复设置
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetSmarterCopyBackState',
        controller.Id,
        ctl_ctx,
        0
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)

    -- 正在工作中
    controller.is_working = true
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetSmarterCopyBackState',
        controller.Id,
        ctl_ctx,
        1
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.is_working = false

    -- 设置回拷返回失败
    sml.ctrl_operation = function()
        return 0x12
    end
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetSmarterCopyBackState',
        controller.Id,
        ctl_ctx,
        1
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 删除受模块管理的对象
    self.object_manager.mc:del_object('Controller', controller, 1)
    self.tasks:run_all_task()
end

-- 测试设置回拷功能
function TestStorage:test_controller_set_jbod_state()
    local controller = add_controller(self)
    -- 设置回拷成功
    sml.ctrl_operation = function()
        return 0
    end
    local rpc_service_controller = self.rpc_service_controller
    local ret =
        pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetJBODState', controller.Id, ctl_ctx, 1)
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)

    -- 不支持带外管理
    controller.OOBSupport = 0
    ret = pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetJBODState', controller.Id, ctl_ctx, 1)
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.OOBSupport = 1

    -- 非法输入
    ret = pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetJBODState', controller.Id, ctl_ctx, 3)
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 重复设置
    ret = pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetJBODState', controller.Id, ctl_ctx, 0)
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)

    -- 正在工作中
    controller.is_working = true
    ret = pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetJBODState', controller.Id, ctl_ctx, 1)
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.is_working = false

    -- 设置回拷返回失败
    sml.ctrl_operation = function()
        return 0x12
    end
    ret = pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetJBODState', controller.Id, ctl_ctx, 1)
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 删除受模块管理的对象
    self.object_manager.mc:del_object('Controller', controller, 1)
    self.tasks:run_all_task()
end

-- 测试恢复默认设置功能
function TestStorage:test_controller_restore_default_settings()
    local controller = add_controller(self)
    -- 设置恢复成功
    sml.ctrl_operation = function()
        return 0
    end
    local rpc_service_controller = self.rpc_service_controller
    local ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'RestoreDefaultSettings',
        controller.Id,
        ctl_ctx
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)

    -- 不支持带外管理
    controller.OOBSupport = 0
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'RestoreDefaultSettings',
        controller.Id,
        ctl_ctx
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.OOBSupport = 1

    -- 正在工作中
    controller.is_working = true
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'RestoreDefaultSettings',
        controller.Id,
        ctl_ctx
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.is_working = false

    -- 返回失败
    sml.ctrl_operation = function()
        return 0x12
    end
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'RestoreDefaultSettings',
        controller.Id,
        ctl_ctx
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 删除受模块管理的对象
    self.object_manager.mc:del_object('Controller', controller, 1)
    self.tasks:run_all_task()
end

-- 测试设置启动设备
function TestStorage:test_controller_set_boot_priority()
    local drive_info = {
        HddBackplaneStartSlot = 10,
        Presence = 1,
        RelativeSlot = 1,
        ObjectName = 'Drive11',
        LocateLed = 1,
        FaultLed = 0,
    }
    self.object_manager.mc:add_object('Drive', drive_info)
    local volume_list = { 12 }
    sml.get_ctrl_ld_list = function(...)
        return volume_list
    end
    sml.get_ld_info = function(...)
        return c_ld_info.new(self.test_ld_info)
    end
    local controller = add_controller(self)
    local drive = self.drive_collection:get_drive(drive_info.Name)
    local pd = { controller_id = controller.Id, slot_num = 2, enclosure_id = 3, device_id = 1, controller_type = 0 }
    local pd_obj = pd_object.new(pd.controller_id, pd, pd.controller_type)
    drive:identified(pd_obj)
    -- 设置成功
    sml.pd_operation = function()
        return 0
    end
    controller.BootDevices = { 'Disk11', 'None' }
    -- 取消启动盘
    local rpc_service_controller = self.rpc_service_controller
    local ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetBootDevices',
        controller.Id,
        ctl_ctx,
        'None',
        'None'
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)
    -- 将Primary启动盘设为Secondary启动盘
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetBootDevices',
        controller.Id,
        ctl_ctx,
        'None',
        'Disk11'
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    -- 将启动盘设为Volume盘
    sml.set_ld_boot_priority = function()
        return 0
    end
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetBootDevices',
        controller.Id,
        ctl_ctx,
        'Volume12',
        'None'
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)
    -- 输入非法名称
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetBootDevices',
        controller.Id,
        ctl_ctx,
        'OKK',
        'None'
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    -- 输入非法序号
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetBootDevices',
        controller.Id,
        ctl_ctx,
        'Disk2',
        'None'
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    -- 输入非法对象
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetBootDevices',
        controller.Id,
        ctl_ctx,
        'OKK2',
        'None'
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    -- 返回错误
    sml.pd_operation = function()
        return 0x12
    end
    controller.BootDevices = { 'None', 'None' }
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetBootDevices',
        controller.Id,
        ctl_ctx,
        'Disk1',
        'None'
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    -- 删除受模块管理的对象
    self.object_manager.mc:del_object('Controller', controller, 1)
    self.tasks:run_all_task()
end

-- 测试设置工作模式功能
function TestStorage:test_controller_set_work_mode()
    local controller = add_controller(self)
    -- 设置成功
    sml.ctrl_operation = function()
        return 0
    end
    local rpc_service_controller = self.rpc_service_controller
    controller.TypeId = 14
    controller.RefChip = { path = 'aaa' }
    local ret =
        pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetWorkMode', controller.Id, ctl_ctx, 2, 0)
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)

    -- 不支持带外管理
    controller.OOBSupport = 0
    ret =
        pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetWorkMode', controller.Id, ctl_ctx, 2, 0)
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.OOBSupport = 1

    -- 非法输入
    ret =
        pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetWorkMode', controller.Id, ctl_ctx, 1, 0)
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 正在工作中
    controller.is_working = true
    ret =
        pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetWorkMode', controller.Id, ctl_ctx, 2, 0)
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.is_working = false

    -- 设置返回失败
    sml.ctrl_operation = function()
        return 12
    end
    local ok, _ = pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'SetWorkMode', controller.Id, 2, 0)
    self.tasks:run_all_task()
    lu.assertEquals(ok, false)

    -- 删除受模块管理的对象
    controller.TypeId = 99
    self.object_manager.mc:del_object('Controller', controller, 1)
    self.tasks:run_all_task()
end

-- 测试导入外部配置功能
function TestStorage:test_controller_import_foreign_config()
    local controller = add_controller(self)
    -- 导入成功
    sml.ctrl_operation = function()
        return 0
    end
    local rpc_service_controller = self.rpc_service_controller
    controller.TypeId = 14
    controller.RefChip = { path = 'aaa' }
    local ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'ImportForeignConfig',
        controller.Id,
        ctl_ctx,
        ''
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)

    -- 不支持带外管理
    controller.OOBSupport = 0
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'ImportForeignConfig',
        controller.Id,
        ctl_ctx,
        ''
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.OOBSupport = 1

    -- 非法输入
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'ImportForeignConfig',
        controller.Id + 1,
        ctl_ctx,
        ''
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 正在工作中
    controller.is_working = true
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'ImportForeignConfig',
        controller.Id,
        ctl_ctx,
        ''
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.is_working = false

    -- 设置导入返回失败
    sml.ctrl_operation = function()
        return 0x12
    end
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'ImportForeignConfig',
        controller.Id,
        ctl_ctx,
        ''
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 删除受模块管理的对象
    controller.TypeId = 99
    self.object_manager.mc:del_object('Controller', controller, 1)
    self.tasks:run_all_task()
end

-- 测试清除外部配置功能
function TestStorage:test_controller_clear_foreign_config()
    local controller = add_controller(self)
    -- 设置成功
    sml.ctrl_operation = function()
        return 0
    end
    local rpc_service_controller = self.rpc_service_controller
    controller.TypeId = 14
    controller.RefChip = { path = 'aaa' }
    local ret =
        pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'ClearForeignConfig', controller.Id, ctl_ctx)
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)

    -- 不支持带外管理
    controller.OOBSupport = 0
    ret =
        pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'ClearForeignConfig', controller.Id, ctl_ctx)
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.OOBSupport = 1

    -- 非法输入
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'ClearForeignConfig',
        controller.Id + 1,
        ctl_ctx
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 正在工作中
    controller.is_working = true
    ret =
        pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'ClearForeignConfig', controller.Id, ctl_ctx)
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.is_working = false

    -- 设置回拷返回失败
    sml.ctrl_operation = function()
        return 0x12
    end
    ret =
        pcall(rpc_service_controller.ctrl_operate, rpc_service_controller, 'ClearForeignConfig', controller.Id, ctl_ctx)
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 删除受模块管理的对象
    controller.TypeId = 14
    self.object_manager.mc:del_object('Controller', controller, 1)
    self.tasks:run_all_task()
end

-- 测试设置回拷功能
function TestStorage:test_controller_storageconfig_ready()
    local storageconfig = self.c_storageconfig
    self.bus_monitor_service.on_os_state_changed:emit(false)
    lu.assertEquals(storageconfig.obj.StorageConfigReady, 0)
    -- 上电但没有raid卡
    storageconfig.power_on = 1
    storageconfig.on_update_flag:emit(4)
    lu.assertEquals(storageconfig.obj.StorageConfigReady, 4)
    -- 上电,有一张读到完整信息了,但另一张不支持带外
    storageconfig.controller_mask = 3
    storageconfig.on_update_flag:emit(2)
    lu.assertEquals(storageconfig.obj.StorageConfigReady, 2)
    storageconfig.configuration_ready_mask = 2
    storageconfig.on_update_flag:emit(1)
    lu.assertEquals(storageconfig.obj.StorageConfigReady, 2)
    -- 先下电再上电
    storageconfig.power_on = 0
    storageconfig.on_update_flag:emit(0)
    storageconfig.power_on = 1
    storageconfig.on_update_flag:emit(4)
    -- 一张正常一张不正常
    storageconfig.controller_mask = 3
    storageconfig.configuration_ready_mask = 2
    storageconfig.on_update_flag:emit(1)
    lu.assertEquals(storageconfig.obj.StorageConfigReady, 3)
    storageconfig.on_update_flag:emit(3)
    lu.assertEquals(storageconfig.obj.StorageConfigReady, 3)
    -- 两张都正常
    storageconfig.controller_mask = 3
    storageconfig.configuration_ready_mask = 3
    storageconfig.on_update_flag:emit(1)
    lu.assertEquals(storageconfig.obj.StorageConfigReady, 1)
    storageconfig.on_update_flag:emit(1)
    lu.assertEquals(storageconfig.obj.StorageConfigReady, 1)
end

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

function TestStorage:test_controller_import_export()
    sml.get_ctrl_sas_addr = function()
        return '0x1100'
    end
    sml.ctrl_operation = function()
        return 0 -- 打桩返回成功
    end
    -- 添加控制器对象
    add_controller(self)

    local storageconfig = self.c_storageconfig
    storageconfig.obj.StorageConfigReady = 1
    self.c_drives_object.obj = {
        LogAutoCollectEnable = true,
        LogAutoCollectInterval = 24,
    }
    import_export_eng.register_config_dealer('RaidController', self.rpc_service_controller)
    local export_str = import_export_eng.export(construct_ctx())
    lu.assertNotEquals(string.find(export_str, '"Type":"SAS3908"'), nil)
    lu.assertNotEquals(string.find(export_str, '"CopybackEnabled":0'), nil)
    lu.assertNotEquals(string.find(export_str, '"Id":0'), nil)
    lu.assertNotEquals(string.find(export_str, '"SMARTerCopybackEnabled":0'), nil)
    lu.assertNotEquals(string.find(export_str, '"JBODEnabled":255'), nil)
    lu.assertNotEquals(string.find(export_str, '"Mode":0'), nil)
    lu.assertNotEquals(string.find(export_str, '"NoBatteryWriteCache":0'), nil)
    lu.assertNotEquals(string.find(export_str, '"ReadCachePercent":0'), nil)
    lu.assertNotEquals(string.find(export_str, '"DrivesLogAutoCollectEnabled":true'), nil)
    lu.assertNotEquals(string.find(export_str, '"DrivesLogAutoCollectInterval":24'), nil)

    local file = io.open('./import.json', 'rb')
    if not file then
        self.object_manager.mc:del_object('Controller', controller, 1)
        self.tasks:run_all_task()
        return
    end
    local file_string = file:read('*a')
    import_export_eng.import(construct_ctx(), file_string)
    self.tasks:run_all_task()
    lu.assertEquals(self.c_drives_object.obj.LogAutoCollectEnable, false)
    lu.assertEquals(self.c_drives_object.obj.LogAutoCollectInterval, 8)

    -- 删除受模块管理的对象
    self.object_manager.mc:del_object('Controller', controller, 1)
end

local controller_1 = {
    Id = 0,
    path = 'Controller_1_0001010102',
    CtrlOption1 = 2275649443,
    CtrlOption2 = 32647,
    CtrlOption3 = 0,
    TypeId = 2,
    OOBSupport = 0,
}
local controller_2 = {
    Id = 1,
    path = 'Controller_2_0001010102',
    CtrlOption1 = 2275649443,
    CtrlOption2 = 32647,
    CtrlOption3 = 0,
    TypeId = 12,
    OOBSupport = 1,
    RefChip = { path = 'Chip_2_0001010102' },
}
local controller_3 = {
    Id = 2,
    path = 'Controller_3_0001010102',
    CtrlOption1 = 2275649443,
    CtrlOption2 = 32647,
    CtrlOption3 = 0,
    TypeId = 99,
    OOBSupport = 1,
}

function TestStorage:test_controller_oob_not_support_mixed()
    local storageconfig = self.c_storageconfig

    -- 没有控制器
    lu.assertEquals(storageconfig:support_oob(), false)

    -- 1个不支持带外管理的控制器
    self.object_manager.mc:add_object('Controller', controller_1, 1)
    self.bus_monitor_service.on_os_state_changed:emit(true)
    self.tasks:run_until(function()
        return #self.controller_collection:get_all_controllers() == 1
    end)
    lu.assertEquals(storageconfig:support_oob(), false)

    -- 1个不支持带外管理的控制器 + 1个3004
    self.object_manager.mc:add_object('Controller', controller_2, 2)
    self.tasks:run_until(function()
        return #self.controller_collection:get_all_controllers() == 2
    end)
    lu.assertEquals(storageconfig:support_oob(), true)

    -- 1个不支持带外管理的控制器 + 1个3004 + 1个非3004
    self.object_manager.mc:add_object('Controller', controller_3, 3)
    self.tasks:run_until(function()
        return #self.controller_collection:get_all_controllers() == 3
    end)
    lu.assertEquals(storageconfig:support_oob(), false)

    -- 1个3004 + 1个非3004
    self.object_manager.mc:del_object('Controller', controller_1, 1)
    self.tasks:run_until(function()
        return #self.controller_collection:get_all_controllers() == 2
    end)
    lu.assertEquals(storageconfig:support_oob(), true)

    -- 恢复
    self.object_manager.mc:del_object('Controller', controller_2, 2)
    self.object_manager.mc:del_object('Controller', controller_3, 3)
    self.tasks:run_all_task()
    lu.assertEquals(storageconfig:support_oob(), false)
end

-- 测试设置控制器无电池写缓存状态
function TestStorage:test_controller_set_no_battery_write_cache()
    local controller = add_controller(self)
    sml.ctrl_operation = function()
        return 0
    end
    local rpc_service_controller = self.rpc_service_controller
    local ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetNoBatteryWriteCache',
        controller.Id,
        ctl_ctx,
        1
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)

    -- 不支持带外管理
    controller.OOBSupport = 0
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetNoBatteryWriteCache',
        controller.Id,
        ctl_ctx,
        1
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.OOBSupport = 1

    -- 非法输入
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetNoBatteryWriteCache',
        controller.Id,
        ctl_ctx,
        3
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 重复设置
    controller.NoBatteryWriteCacheEnabled = 0
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetNoBatteryWriteCache',
        controller.Id,
        ctl_ctx,
        0
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)

    -- 正在工作中
    controller.is_working = true
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetNoBatteryWriteCache',
        controller.Id,
        ctl_ctx,
        1
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.is_working = false

    -- 设置回拷返回失败
    sml.ctrl_operation = function()
        return 0x12
    end
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetNoBatteryWriteCache',
        controller.Id,
        ctl_ctx,
        1
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 删除受模块管理的对象
    self.object_manager.mc:del_object('Controller', controller, 1)
    self.tasks:run_all_task()
end

-- 测试设置控制器读缓存百分比
function TestStorage:test_controller_set_read_cache_percent()
    local controller = add_controller(self)
    sml.ctrl_operation = function()
        return 0
    end
    local rpc_service_controller = self.rpc_service_controller
    local ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetReadCachePercent',
        controller.Id,
        ctl_ctx,
        60
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)

    -- 不支持带外管理
    controller.OOBSupport = 0
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetReadCachePercent',
        controller.Id,
        ctl_ctx,
        60
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.OOBSupport = 1

    -- 非法输入
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetReadCachePercent',
        controller.Id,
        ctl_ctx,
        200
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 重复设置
    controller.ReadCachePercent = 80
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetReadCachePercent',
        controller.Id,
        ctl_ctx,
        80
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)

    -- 正在工作中
    controller.is_working = true
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetReadCachePercent',
        controller.Id,
        ctl_ctx,
        1
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.is_working = false

    -- 设置回拷返回失败
    sml.ctrl_operation = function()
        return 0x12
    end
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetReadCachePercent',
        controller.Id,
        ctl_ctx,
        60
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 删除受模块管理的对象
    self.object_manager.mc:del_object('Controller', controller, 1)
    self.tasks:run_all_task()
end

-- 测试控制器dump日志
function TestStorage:test_controller_dump_info()
    -- 添加控制器对象
    local obj = add_controller(self)
    lu.assertNotIsNil(obj)
    local obj_info_path = project_dir .. '/test/unit/raid_controller_info.txt'
    local fp_w = file_sec.open_s(obj_info_path, 'w+')
    lu.assertNotIsNil(fp_w)

    -- 调用控制器收集日志到桩文件中
    obj.FaultCode = 1
    obj:dump_info(fp_w)
    fp_w:close()

    local file = file_sec.open_s(obj_info_path, 'r')
    lu.assertNotIsNil(file)
    local content = utils.close(file, pcall(file.read, file, '*a'))
    lu.assertNotIsNil(content)
    -- 检查控制器收集的信息
    lu.assertNotEquals(string.find(content, 'Battery Write Cache                        : Enabled'), nil)
    lu.assertNotEquals(string.find(content, 'Read Cache Percentage                         : 0'), nil)
    lu.assertNotEquals(string.find(content, 'Unonfigured Drives Write Cache Policy         : Default'), nil)
    lu.assertNotEquals(string.find(content, 'HBA Drives Write Cache Policy                 : Default'), nil)
    lu.assertNotEquals(string.find(content, 'Configured Drives Write Cache Policy          : Default'), nil)

    utils.remove_file(obj_info_path)
    -- 删除受模块管理的对象
    self.object_manager.mc:del_object('Controller', controller, 1)
    self.tasks:run_all_task()
end

-- 测试设置控制器写缓存策略
function TestStorage:test_controller_set_write_cache_policy()
    local controller = add_controller(self)
    sml.ctrl_operation = function()
        return 0
    end
    local rpc_service_controller = self.rpc_service_controller
    local ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetWriteCachePolicy',
        controller.Id,
        ctl_ctx,
        'ConfiguredDriveWriteCachePolicy',
        'Enabled'
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)

    -- 不支持带外管理
    controller.OOBSupport = 0
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetWriteCachePolicy',
        controller.Id,
        ctl_ctx,
        'ConfiguredDriveWriteCachePolicy',
        'Default'
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.OOBSupport = 1

    -- 非法输入
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetWriteCachePolicy',
        controller.Id,
        ctl_ctx,
        'ConfiguredDriveWriteCachePolicy',
        'test'
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 重复设置
    controller.ConfiguredDriveWriteCachePolicy = 'Default'
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetWriteCachePolicy',
        controller.Id,
        ctl_ctx,
        'ConfiguredDriveWriteCachePolicy',
        'Default'
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, true)

    -- 正在工作中
    controller.is_working = true
    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetWriteCachePolicy',
        controller.Id,
        ctl_ctx,
        'ConfiguredDriveWriteCachePolicy',
        'Default'
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)
    controller.is_working = false

    -- 打桩设置返回失败
    sml.ctrl_operation = function()
        return 0x12
    end

    ret = pcall(
        rpc_service_controller.ctrl_operate,
        rpc_service_controller,
        'SetWriteCachePolicy',
        controller.Id,
        ctl_ctx,
        'UnconfiguredDriveWriteCachePolicy',
        'Enabled'
    )
    self.tasks:run_all_task()
    lu.assertEquals(ret, false)

    -- 删除受模块管理的对象
    self.object_manager.mc:del_object('Controller', controller, 1)
    self.tasks:run_all_task()
end

-- 测试Raid卡核温负温场景
function TestStorage:test_raid_negative_temperature()
    -- 打桩Raid卡温度为-1(65535)度
    self.test_controller_data['ctrl_temp'] = 65535
    local controller = add_controller(self)
    -- 校验结果:更新到资源树的温度为-1度,符合预期
    lu.assertEquals(controller.TemperatureCelsius, -1)
end

-- 测试文件安全函数调用
function TestStorage:test_collect_raid_bin_format_log()
    local ret = pcall(controller_collection.collect_raid_bin_format_log)
    lu.assertEquals(ret, true)
end

function TestStorage:test_set_controller_outofband()
    add_controller(self)
    local ctx = construct_ctx()
    local req = {}
    req.ManufacturerId = 0x0007DB
    req.WritingLength = 1
    req.WritingOffset = 0
    req.Frame = 0
    req.Controller = 1
    req.Data = string.char(0)
    ipmi.set_controller_outofband(req, ctx)
end

function TestStorage:test_set_controller_outofband2()
    add_controller(self)
    local ctx = construct_ctx()
    local req = {}
    req.ManufacturerId = 0x0007DB
    req.WritingLength = 1
    req.WritingOffset = 0
    req.Frame = 0
    req.Controller = 1
    req.Data = string.char(3)

    local mock_persist = {}
    function mock_persist:per_save(a, b, c) end
    controller_collection.get_instance().persist = mock_persist
    ipmi.set_controller_outofband(req, ctx)
end

function TestStorage:test_update_controller_battery_info()
    c_controller.presence_debounce = debounce[debounce.DEBOUNCED_CONT].new(5, common_def.INVALID_U8)
    c_controller.BatteryHealth = 1
    local mock_persist = function(...)
        return { State = 6, Fault = 0, Health = 0 }
    end
    battery_collection.get_instance().get_capcacitance_by_controller_id = mock_persist
    c_controller:update_controller_battery_info()
end

function TestStorage:test_record_commu_loss()
    local c_power_on = c_storageconfig.get_instance().power_on
    c_storageconfig.get_instance().power_on = 0
    local ok = c_controller.record_commu_loss()
    lu.assertEquals(ok, nil)
    c_storageconfig.get_instance().power_on = 1
    local c_update = c_ctrl_commu_loss_monitor.get_instance().update
    c_ctrl_commu_loss_monitor.get_instance().update = function()
        return true
    end
    ok = c_controller.record_commu_loss(0x1001)
    c_ctrl_commu_loss_monitor.get_instance().update = c_update
    c_storageconfig.get_instance().power_on = c_power_on
    lu.assertEquals(ok, nil)
end

function TestStorage:test_before_add_object()
    c_controller.DeviceName = 'PCIe Card !'
    c_controller:before_add_object(c_controller.DeviceName)
end

function TestStorage:test_register()
    self.object_manager.mc:add_object('Controller', controller, 1)
    local c_power_on = c_storageconfig.get_instance().power_on
    c_storageconfig.get_instance().power_on = 0
    self.tasks:run_task('register_controller')
    c_storageconfig.get_instance().power_on = c_power_on
    self.object_manager.mc:del_object('Controller', controller, 1)
end