-- Copyright (c) 2025 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 file_sec = require 'utils.file'
local utils = require 'mc.utils'
local c_controller = require 'controller.controller_object'
local drive_collection = require 'drive.drive_collection'
local volume_collection = require 'volume.volume_collection'
local controller_collection = require 'controller.controller_collection'
local array_collection = require 'array.array_collection'
local volume_obj_info = require 'volume.volume_obj_info'
local ipmi_service = require 'ipmi_service'
local project_dir = os.getenv('PROJECT_DIR')

TEST_ipmi = {}

-- 测试获取指定逻辑盘对应的物理盘ID（ipmi_service 使用 get_instance():get_ctrl_volume_by_id，需 stub get_instance）
function TEST_ipmi:test_get_logical_drive_pds()
    local req = {
        ManufacturerId = 0x0007DB,
        ControllerId = 0,
        VolumeId = 0
    }
    local orig_get_instance = volume_collection.get_instance
    volume_collection.get_instance = function()
        return {
            get_ctrl_volume_by_id = function(_, _cid, _vid)
                return {["RefDriveList"] = {"Drive_3", "Drive_5"}}
            end
        }
    end
    drive_collection.get_instance().get_drive = function (self, drive_name)
        return {["Id"] = tonumber(string.match(drive_name, "_(%d+)$"))}
    end
    rsp = ipmi_service.get_logical_drive_pds(req,{})
    -- 检查信息
    lu.assertEquals(rsp.CompletionCode, 0)
    lu.assertEquals(rsp.ManufactureId, 0x0007DB)
    lu.assertNotEquals(rsp.Data, nil)
    local result = {}
    local pos = 1
    while pos <= #rsp.Data do
        local value, new_pos = string.unpack('B', rsp.Data, pos)
        table.insert(result, value)
        pos = new_pos
    end
    lu.assertEquals(result, {3, 5})

    volume_collection.get_instance = function()
        return {
            get_ctrl_volume_by_id = function(_, _cid, _vid)
                return nil
            end
        }
    end
    rsp = ipmi_service.get_logical_drive_pds(req,{})
    lu.assertEquals(rsp.CompletionCode, 0xcb)

    volume_collection.get_instance = orig_get_instance
end

function TEST_ipmi:test_get_cachecade_associated_lds_base()
    local req = {
        ManufacturerId = 0x0007DB,
        ControllerId = 0,
        VolumeId = 0
    }
    local orig_get_instance = volume_collection.get_instance
    volume_collection.get_instance = function()
        return {
            get_ctrl_volume_by_id = function(_, _cid, _vid)
                return {["AssociatedCacheCadeVolume"] = {1}}
            end
        }
    end
    rsp = ipmi_service.get_cachecade_associated_lds(req, {})
    -- 检查信息
    lu.assertEquals(rsp.CompletionCode, 0)
    lu.assertEquals(rsp.ManufactureId, 0x0007DB)
    lu.assertNotEquals(rsp.Data, nil)
    local result = {}
    local pos = 1
    while pos <= #rsp.Data do
        local value, new_pos = string.unpack('B', rsp.Data, pos)
        table.insert(result, value)
        pos = new_pos
    end
    lu.assertEquals(result, {1})

    volume_collection.get_instance = function()
        return {
            get_ctrl_volume_by_id = function(_, _cid, _vid)
                return nil
            end
        }
    end
    rsp = ipmi_service.get_cachecade_associated_lds(req, {})
    lu.assertEquals(rsp.CompletionCode, 0xcb)

    volume_collection.get_instance = orig_get_instance
end

function TEST_ipmi:test_get_controller_fw_version()
    local req = {
        ManufacturerId = 0x0107DB,
        ControllerId = 0,
    }
    rsp = ipmi_service.get_controller_fw_version(req,{})
    lu.assertEquals(rsp.CompletionCode, 0xcc)

    req.ManufacturerId = 0x0007DB

    c_controller.collection = {
        ['find'] = function(...) return nil end ,
        ['fold'] = function(...) return nil end
    }
    controller_collection.new().get_by_controller_id = function (...)
        return  nil
    end
    rsp = ipmi_service.get_controller_fw_version(req,{})
    lu.assertEquals(rsp.CompletionCode, 0xcb)
end

function TEST_ipmi:test_get_array_pds()
    local req = {
        ManufacturerId = 0x0107DB,
        ArrayIDHigh = 0,
        ArrayIDLow =0
    }
    rsp = ipmi_service.get_array_pds(req,{})
    lu.assertEquals(rsp.CompletionCode, 0xcc)

    req.ManufacturerId = 0x0007DB
    storage_app = {
        bus = 1
    }
    array_collection.new(storage_app).get_ctrl_array_by_id = function (...)
        return  nil
    end
    rsp = ipmi_service.get_array_pds(req,{})
    lu.assertEquals(rsp.CompletionCode, 0xcb)
end

function TEST_ipmi:test_get_physical_drive_led_status()
    local req = {
        ManufacturerId = 0x0107DB,
        PhysicalDriveID = 0
    }
    rsp = ipmi_service.get_physical_drive_led_status(req,{})
    lu.assertEquals(rsp.CompletionCode, 0xcc)

    req.ManufacturerId = 0x0007DB
    storage_app = {
        bus = 1
    }
    drive_collection.new().get_drive_by_drive_id = function (...)
        return  nil
    end
    rsp = ipmi_service.get_physical_drive_led_status(req,{})
    lu.assertEquals(rsp.CompletionCode, 0xcb)
end

function TEST_ipmi:test_set_logical_drive_name()
    local req = {
        ManufacturerId = 0x0107DB,
        Data ={},
        WritingLength = 1,
        WritingOffset = 1
    }
    rsp = ipmi_service.set_logical_drive_name(req,{})
    lu.assertEquals(rsp.CompletionCode, 0xcc)

    req.Data = {0}
    rsp = ipmi_service.set_logical_drive_name(req,{})
    lu.assertEquals(rsp.CompletionCode, 0xcc)
end

function TEST_ipmi:test_start_drive_collect_log()
    local req = {
        ManufacturerId = 0x0107DB,
    }
    rsp = ipmi_service.start_drive_collect_log(req,{})
    lu.assertEquals(rsp.CompletionCode, 0xcc)
end

function TEST_ipmi:test_get_log_auto_collect_config()
    local req = {
        ManufacturerId = 0x0107DB,
    }
    rsp = ipmi_service.get_log_auto_collect_config(req,{})
    lu.assertEquals(rsp.CompletionCode, 0xcc)
end

function TEST_ipmi:test_set_log_auto_collect_config()
    local req = {
        ManufacturerId = 0x0107DB,
    }
    rsp = ipmi_service.set_log_auto_collect_config(req,{})
    lu.assertEquals(rsp.CompletionCode, 0xcc)
end

function TEST_ipmi:test_set_pd_log_collect()
    local req = {
        ManufacturerId = 0x0107DB,
    }
    rsp = ipmi_service.set_pd_log_collect(req,{})
    lu.assertEquals(rsp.CompletionCode, 0xcc)
end

function TEST_ipmi:test_get_manufacturer()
    local req = {
        ManufacturerId = 0x0107DB,
    }
    rsp = ipmi_service.get_manufacturer(req,{})
    lu.assertEquals(rsp.CompletionCode, 0xcc)
end

function TEST_ipmi:test_set_raid_fault_status()
    local req = {
        ManufacturerId = 0x0007DB,
        DeviceStatus1 = 0,
        Bus = 1,
        Device = 2,
        Function = 3
    }
    c_controller.collection = {
        ['find'] = function(...) return {
            pcb_version = "N/A"
        } end ,
        ['fold'] = function(...) return nil end
    }
    controller_collection.new().get_all_controllers = function (...)
        return  {}
    end
    rsp = ipmi_service.set_raid_fault_status(req,{})
    lu.assertEquals(rsp.CompletionCode, 0xcc)
end

function TEST_ipmi:test_get_controller_info()
    local req = {
        ManufacturerId = 0x0007DB,
        ControllerId = 0,
        ReadingOffset = 0,
        ReadingLength = 0xF0
    }
    c_controller.collection = {
        ['find'] = function(...) return {
            pcb_version = "N/A"
        } end ,
        ['fold'] = function(...) return nil end
    }
    controller_collection.new().get_by_controller_id = function (...)
        return  {
            OOBSupport = 0,
            MemorySizeMiB = 0,
            CachePinnedState = 0,
            MaintainPDFailHistrory = 0,
            CopyBackState = 0,
            SmarterCopyBackState = 0,
            JBODState = 0,
            ControllerName = "test",
            SASAddr = 'abcd'
        }
    end
    local rsp = ipmi_service.get_controller_info(req,{})
    lu.assertEquals(rsp.CompletionCode, 0x00)
end
