local lu = require('luaunit')
TestMctpObject = {}
local saved_pkg_obj = {}
local function save_obj_packages(keys)
for _, k in ipairs(keys) do
saved_pkg_obj[k] = package.loaded[k]
end
end
local function restore_obj_packages()
for k, v in pairs(saved_pkg_obj) do
if v == nil then
package.loaded[k] = nil
else
package.loaded[k] = v
end
end
saved_pkg_obj = {}
end
local function setup_mctp_object_mocks(opts)
opts = opts or {}
package.loaded['mctp.mctp_object'] = nil
local keys = { 'mctp_lib', 'mc.logging', 'common_def' }
save_obj_packages(keys)
package.loaded['mctp_lib'] = {
bdf_to_phy_addr = opts.bdf_to_phy_addr or function(bus, dev, func)
return 42
end,
get_endpoint_and_transport = opts.get_endpoint_and_transport or function(...)
return {}, {}
end,
}
package.loaded['mc.logging'] = {
debug = function() end,
info = function() end,
notice = function() end,
error = function() end,
}
package.loaded['common_def'] = {
PMC_3152_8I_SMART_RAID = 64,
PMC_2100_8I_SMART_HBA = 65,
PMC_8204_8I_SMART_RAID = 66,
PMC_8254_8I_SMART_RAID = 67,
PMC_8222_8I_SMART_RAID = 68,
}
return require('mctp.mctp_object')
end
function TestMctpObject:tearDown()
restore_obj_packages()
package.loaded['mctp.mctp_object'] = nil
end
function TestMctpObject:test_new_pmc_raid()
local mctp_obj_module = setup_mctp_object_mocks()
local controller = {
Id = 1,
DevBus = 10,
DevDevice = 5,
DevFunction = 3,
TypeId = 64,
}
local obj = mctp_obj_module.new('mock_bus', controller)
lu.assertEquals(obj.phy_addr, 42)
lu.assertEquals(obj.id, 1)
lu.assertEquals(obj.bus, 'mock_bus')
lu.assertEquals(obj.vendor_id, 0x9005)
lu.assertEquals(controller.Phyaddr, 42)
end
function TestMctpObject:test_new_huawei_raid()
local mctp_obj_module = setup_mctp_object_mocks()
local controller = {
Id = 2,
DevBus = 20,
DevDevice = 0,
DevFunction = 1,
TypeId = 96,
}
local obj = mctp_obj_module.new('mock_bus', controller)
lu.assertEquals(obj.phy_addr, 42)
lu.assertEquals(obj.vendor_id, 0x1E81)
end
function TestMctpObject:test_is_pmc_raid()
local mctp_obj_module = setup_mctp_object_mocks()
lu.assertTrue(mctp_obj_module.is_pmc_raid(64))
lu.assertTrue(mctp_obj_module.is_pmc_raid(65))
lu.assertFalse(mctp_obj_module.is_pmc_raid(96))
lu.assertFalse(mctp_obj_module.is_pmc_raid(0))
end
function TestMctpObject:test_register_ctrl_mctp_transport_success()
local transport_mock = { eid = 8 }
local mctp_obj_module = setup_mctp_object_mocks({
get_endpoint_and_transport = function(bus, name, phy_addr, msg_type)
return { TargetEid = 8 }, transport_mock
end,
})
local controller = {
Id = 1,
DevBus = 10,
DevDevice = 5,
DevFunction = 3,
TypeId = 96,
}
local obj = mctp_obj_module.new('mock_bus', controller)
obj:register_ctrl_mctp_transport()
lu.assertEquals(obj.transport, transport_mock)
end
function TestMctpObject:test_register_ctrl_mctp_transport_fail()
local mctp_obj_module = setup_mctp_object_mocks({
get_endpoint_and_transport = function(...)
error('transport error')
end,
})
local controller = {
Id = 1,
DevBus = 10,
DevDevice = 5,
DevFunction = 3,
TypeId = 96,
}
local obj = mctp_obj_module.new('mock_bus', controller)
local ok = pcall(obj.register_ctrl_mctp_transport, obj)
lu.assertFalse(ok)
end
TestMctpService = {}
local saved_pkg_svc = {}
local function save_svc_packages(keys)
for _, k in ipairs(keys) do
saved_pkg_svc[k] = package.loaded[k]
end
end
local function restore_svc_packages()
for k, v in pairs(saved_pkg_svc) do
if v == nil then
package.loaded[k] = nil
else
package.loaded[k] = v
end
end
saved_pkg_svc = {}
end
local function setup_mctp_service_mocks(opts)
opts = opts or {}
package.loaded['mctp.mctp_service'] = nil
local keys = {
'mctp.mctp_object',
'mc.logging',
'mc.singleton',
'sml.core',
'sml',
'mc.orm.tasks',
'mc.class',
'mctp_lib',
'storage_bus',
}
save_svc_packages(keys)
package.loaded['mctp.mctp_object'] = {
new = function(bus, controller)
return {
id = controller.Id,
eid = 0,
phy_addr = 42,
vendor_id = 0x1E81,
register_ctrl_mctp_transport = function() end,
}
end,
is_pmc_raid = function(type_id)
return false
end,
}
local log_calls = {}
package.loaded['mc.logging'] = {
debug = function() end,
info = function() end,
notice = function(_, fmt, ...)
table.insert(log_calls, string.format(fmt, ...))
end,
error = function() end,
}
package.loaded['mc.class'] = function()
local cls = {}
function cls.new(...)
local instance = {}
setmetatable(instance, { __index = cls })
local ctor = rawget(cls, 'ctor')
if ctor then
ctor(instance, ...)
end
local init = rawget(cls, 'init')
if init then
init(instance, ...)
end
return instance
end
return cls
end
local singleton_instance
package.loaded['mc.singleton'] = function(cls)
local wrapped = {}
function wrapped.new(...)
if not singleton_instance then
singleton_instance = cls.new(...)
end
return singleton_instance
end
function wrapped.get_instance()
return singleton_instance
end
function wrapped.destroy()
singleton_instance = nil
end
return wrapped
end
local mock_mctp_infos = {
set_bmc_mctp_info = function() end,
add_mctp_info = function() end,
del_mctp_info = function() end,
}
package.loaded['sml.core'] = { mctp_infos = mock_mctp_infos }
package.loaded['sml'] = { mctp_infos = mock_mctp_infos }
local task_mock = {}
task_mock._stopped = false
task_mock.loop = function(self, fn)
task_mock._fn = fn
return task_mock
end
task_mock.set_timeout_ms = function(self, ms)
return task_mock
end
task_mock.stop = function(self)
task_mock._stopped = true
end
package.loaded['mc.orm.tasks'] = {
get_instance = function()
return {
new_task = function(name)
return task_mock
end,
}
end,
}
package.loaded['mctp_lib'] = {
get_mctp_pcie_binding = opts.get_mctp_pcie_binding or function(bus)
return { BmcEid = 1, BmcPhyAddr = 2 }
end,
get_pcie_endpoint = function(...)
return { TargetEid = 8 }
end,
MCTP_MESSAGE_TYPE_VDPCI = 0x7E,
}
package.loaded['storage_bus'] = {
get_instance = function()
return { bus = 'mock_bus' }
end,
}
local mctp_service = require('mctp.mctp_service')
return {
module = mctp_service,
task_mock = task_mock,
log_calls = log_calls,
mock_mctp_infos = mock_mctp_infos,
}
end
function TestMctpService:tearDown()
restore_svc_packages()
saved_pkg_svc = {}
package.loaded['mctp.mctp_service'] = nil
end
function TestMctpService:test_init_creates_task()
local ctx = setup_mctp_service_mocks()
local svc = ctx.module.new()
svc:init()
lu.assertNotNil(svc.mctp_start_task)
lu.assertNotNil(ctx.task_mock._fn)
end
function TestMctpService:test_loop_with_mctp_state_true()
local ctx = setup_mctp_service_mocks()
local svc = ctx.module.new()
svc.os_state = true
svc:init()
local task = svc.mctp_start_task
task._fn(task)
lu.assertEquals(svc.mctp_state, true)
lu.assertTrue(ctx.task_mock._stopped)
lu.assertNil(svc.mctp_start_task)
lu.assertTrue(#ctx.log_calls > 0)
end
function TestMctpService:test_prepare_success()
local ctx = setup_mctp_service_mocks()
local svc = ctx.module.new()
svc.os_state = true
svc:prepare()
lu.assertEquals(svc.mctp_state, true)
lu.assertTrue(#ctx.log_calls > 0)
local found = false
for _, msg in ipairs(ctx.log_calls) do
if string.find(msg, 'mctp prepare finished') then
found = true
break
end
end
lu.assertTrue(found)
end
function TestMctpService:test_prepare_os_state_false()
local ctx = setup_mctp_service_mocks()
local svc = ctx.module.new()
svc.os_state = false
svc:prepare()
lu.assertEquals(svc.mctp_state, false)
end
function TestMctpService:test_prepare_no_binding()
local ctx = setup_mctp_service_mocks({
get_mctp_pcie_binding = function(bus)
return nil
end,
})
local svc = ctx.module.new()
svc.os_state = true
svc:prepare()
lu.assertEquals(svc.mctp_state, false)
end