-- 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
    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)

    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()

    -- 删除受模块管理的对象
    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()
    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
