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

-- require所有依赖
local log = require 'mc.logging'
local ctx = require 'mc.context'
local mdb = require 'mc.mdb'
local c_factory = require 'mc.orm.factory'
local sd_bus = require 'sd_bus.org_freedesktop_dbus'
local c_network_adapter = require 'device.class.network_adapter'
local comm_fun = require 'device.class.nic_mgmt.comm_fun'
local comm_defs = require 'device.class.nic_mgmt.comm_defs'
local card_init = require 'device.class.nic_mgmt.card.card_init'
local c_network_adapter_preload = require 'device.class.network_adapter_preload'
local c_object_manage = require 'mc.orm.object_manage'

local card_mgmt = require 'device.class.nic_mgmt.card_mgmt'

-- -- 记录原始实现
-- local origs = {}
-- local function save_orig(tbl, key)
--     origs[tbl] = origs[tbl] or {}
--     origs[tbl][key] = tbl[key]
-- end
-- local function restore_all()
--     for tbl, keys in pairs(origs) do
--         for k, v in pairs(keys) do tbl[k] = v end
--     end
-- end

TestCardMgmt = {}

-- function TestCardMgmt:setUp()
--     -- mock log
--     save_orig(log, 'notice')
--     save_orig(log, 'error')
--     log.notice = function() end
--     log.error = function() end
--     -- mock comm_fun
--     save_orig(comm_fun, 'set_interface_add_signal')
--     save_orig(comm_fun, 'get_object_name_by_device_path')
--     save_orig(comm_fun, 'get_object_identifier_by_device_path')
--     save_orig(comm_fun, 'get_all_device_paths')
--     save_orig(comm_fun, 'get_device_obj_by_path_interface')
--     save_orig(comm_fun, 'set_interface_del_signal')
--     save_orig(comm_fun, 'get_position_by_object_name')
--     comm_fun.set_interface_add_signal = function(bus, sig_slot, pattern, iface, cb)
--         TestCardMgmt._called_set_interface_add_signal = { bus, sig_slot, pattern, iface, cb }
--         cb('/mock/path')
--     end
--     comm_fun.set_interface_del_signal = function(bus, sig_slot, pattern, iface, cb)
--         sig_slot[#sig_slot + 1] = 456
--         if not bus.match then
--             bus.match = function() return 456 end
--         end
--     end
--     comm_fun.get_object_name_by_device_path = function() return 'obj_name' end
--     comm_fun.get_object_identifier_by_device_path = function() return {1, 'test_manager', 'test_chassis', 'test_position'} end
--     comm_fun.get_position_by_object_name = function(object_name) return '1' end
--     comm_fun.get_all_device_paths = function() return { '/mock/path' } end
--     comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--         -- 返回一个包含 SmBiosStatus 属性的对象，用于 init_smbios_status
--         if interface == comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE then
--             return { SmBiosStatus = 0 }
--         end
--         return {}
--     end
--     -- mock comm_defs
--     save_orig(comm_defs, 'CARD_DEVICE_PATH_PATTERN')
--     save_orig(comm_defs, 'NETWORK_ADAPTER_DEVICE_INTERFACE')
--     save_orig(comm_defs, 'MACA_SERVICE')
--     save_orig(comm_defs, 'MDB_PATH')
--     save_orig(comm_defs, 'MDB_INTERFACE')
--     save_orig(comm_defs, 'PCIE_DEVICE_INTERFACE')
--     save_orig(comm_defs, 'PCIE_CARD_DEVICE_INTERFACE')
--     comm_defs.CARD_DEVICE_PATH_PATTERN = '/mock/pattern'
--     comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE = 'iface'
--     comm_defs.MACA_SERVICE = 'svc'
--     comm_defs.MDB_PATH = '/mdb'
--     comm_defs.MDB_INTERFACE = 'mdb_iface'
--     comm_defs.PCIE_DEVICE_INTERFACE = 'iface1'
--     comm_defs.PCIE_CARD_DEVICE_INTERFACE = 'iface2'
--     -- mock ctx
--     save_orig(ctx, 'get_context_or_default')
--     ctx.get_context_or_default = function() return {} end
--     -- mock mdb
--     save_orig(mdb, 'register_interface')
--     save_orig(mdb, 'get_object')
--     mdb.register_interface = function() end
--     mdb.get_object = function()
--         return {
--             get_property = function(self, prop)
--                 if prop == 'DeviceName' then return 0, 'NodeId' end
--                 return 0, 'val'
--             end
--         }
--     end
--     -- mock c_network_adapter
--     save_orig(c_network_adapter, 'create_mdb_object')
--     save_orig(c_network_adapter, 'collection')
--     c_network_adapter.create_mdb_object = function(tbl) return tbl end
--     c_network_adapter.collection = {
--         find = function(self, q)
--             return { children = {}, NetworkPortCount = 1, NodeId = q and q.ID or 'NodeId' }
--         end,
--         del_object = function() end
--     }
--     -- mock c_factory
--     save_orig(c_factory, 'get_instance')
--     c_factory.get_instance = function() return { create_object = function() end } end
--     -- mock card_init
--     save_orig(card_init, 'init')
--     TestCardMgmt._card_init_called = {}
--     card_init.init = function(obj) TestCardMgmt._card_init_called.obj = obj end
--     -- mock sd_bus
--     save_orig(sd_bus, 'ObjMgrPropertiesChanged')
--     save_orig(sd_bus, 'MatchRule')
--     sd_bus.ObjMgrPropertiesChanged = { name = 'n', interface = 'i' }
--     sd_bus.MatchRule = { signal = function() return { with_path = function() return 'sig' end } end }
--     -- mock skynet
--     local skynet = require 'skynet'
--     save_orig(skynet, 'sleep')
--     skynet.sleep = function() end
--     -- mock client
--     local client = require 'network_adapter.client'
--     save_orig(client, 'OnComponentPropertiesChanged')
--     save_orig(client, 'ForeachComponentObjects')
--     save_orig(client, 'GetComponentObjects')
--     save_orig(client, 'OnFruCtrlPropertiesChanged')
--     save_orig(client, 'OnSmBiosInterfacesAdded')
--     save_orig(client, 'OnSmBiosPropertiesChanged')
--     save_orig(client, 'GetSmBiosObjects')
--     save_orig(client, 'OnFruCtrlInterfacesAdded')
--     client.OnComponentPropertiesChanged = function(self, callback) end
--     client.ForeachComponentObjects = function(self, callback) end
--     client.GetComponentObjects = function(self) return {} end
--     client.OnFruCtrlPropertiesChanged = function(self, callback) end
--     client.OnSmBiosInterfacesAdded = function(self, callback) end
--     client.OnSmBiosPropertiesChanged = function(self, callback) end
--     client.GetSmBiosObjects = function(self) return {} end
--     client.OnFruCtrlInterfacesAdded = function(self, callback) end
--     -- mock fructl
--     local fructl = require 'infrastructure.fructl'
--     save_orig(fructl, 'get_power_status')
--     fructl.get_power_status = function() return 'ON' end
-- end

-- function TestCardMgmt:tearDown()
--     restore_all()
-- end

-- function TestCardMgmt:test_ctor_and_init()
--     local bus = {}
--     local mgr = card_mgmt
--     mgr.bus = bus
--     mgr.objects = {}
--     mgr.sig_slot = {}
--     lu.assertIs(mgr.bus, bus)
--     lu.assertIsTable(mgr.objects)
--     lu.assertIsTable(mgr.sig_slot)
-- end

-- function TestCardMgmt:test_init_obj_and_register_children()
--     local bus = {}
--     local mgr = card_mgmt
--     mgr.bus = bus
--     mgr.objects = {}
--     mgr.sig_slot = {}
--     -- mock bus:call，确保get_node_id_by_device_path能正常返回
--     bus.call = function(self, service, path, interface, method, signature, context, device_path, interfaces)
--         return { ['svc'] = { 'iface1' } }
--     end
--     -- 执行
--     mgr:init_obj('/mock/path')
--     lu.assertIsTable(mgr.objects['/mock/path'])
--     local card_orm_obj = mgr.objects['/mock/path']
--     local port_orm_obj = { id = 1 }
--     mgr:register_children(port_orm_obj, card_orm_obj)
--     lu.assertEquals(card_orm_obj.children[1], port_orm_obj)
--     lu.assertIs(TestCardMgmt._card_init_called.obj, card_orm_obj)
-- end

-- function TestCardMgmt:test_get_orm_obj_by_device_path()
--     local bus = {}
--     local mgr = card_mgmt
--     mgr.bus = bus
--     mgr.objects = { ['/mock/path'] = { id = 1 } }
--     local obj = mgr:get_orm_obj_by_device_path('/mock/path')
--     lu.assertEquals(obj.id, 1)
--     local obj2 = mgr:get_orm_obj_by_device_path('/notfound')
--     lu.assertNil(obj2)
-- end

-- function TestCardMgmt:test_init()
--     local bus = {}
--     local mgr = card_mgmt
--     mgr.bus = bus
--     mgr.objects = {}
--     mgr.sig_slot = {}
--     -- mock bus:call，确保get_node_id_by_device_path能正常返回
--     bus.call = function(self, service, path, interface, method, signature, context, device_path, interfaces)
--         return { ['svc'] = { 'iface1' } }
--     end
--     -- 执行
--     mgr:init()
--     lu.assertIsTable(mgr.objects['/mock/path'])
-- end

-- function TestCardMgmt:test_create_card_orm_object_nodeid_nil()
--     local orig_get_object = mdb.get_object
--     mdb.get_object = function() return { get_property = function() return 1, nil end } end
--     local mgr = card_mgmt
--     mgr.bus = {}
--     mgr.objects = {}
--     mgr.sig_slot = {}
--     mgr:init_obj('/mock/path')
--     lu.assertNil(mgr.objects['/mock/path'])
--     mdb.get_object = orig_get_object
-- end

-- function TestCardMgmt:test_create_card_orm_object_objectname_nil()
--     local orig_get_object_name = comm_fun.get_object_name_by_device_path
--     comm_fun.get_object_name_by_device_path = function() return nil end
--     local mgr = card_mgmt
--     mgr.bus = {}
--     mgr.objects = {}
--     mgr.sig_slot = {}
--     mgr:init_obj('/mock/path')
--     lu.assertNil(mgr.objects['/mock/path'])
--     comm_fun.get_object_name_by_device_path = orig_get_object_name
-- end

-- function TestCardMgmt:test_init_obj_already_exists()
--     local bus = {}
--     local mgr = card_mgmt
--     mgr.bus = bus
--     mgr.objects = { ['/mock/path'] = { id = 1 } }
--     mgr.sig_slot = {}
--     mgr:init_obj('/mock/path')
--     lu.assertEquals(mgr.objects['/mock/path'].id, 1)
-- end

-- function TestCardMgmt:test_get_orm_obj_by_device_path_log_error()
--     local log_err_called = false
--     local orig_error = log.error
--     log.error = function() log_err_called = true end
--     local bus = {}
--     local mgr = card_mgmt
--     mgr.bus = bus
--     mgr.objects = {}
--     local obj = mgr:get_orm_obj_by_device_path('/notfound')
--     lu.assertNil(obj)
--     lu.assertTrue(log_err_called)
--     log.error = orig_error
-- end

-- function TestCardMgmt:test_firmware_version_sync_to_ports()
--     local port1 = { FirmwareVersion = "old_version_1" }
--     local port2 = { FirmwareVersion = "old_version_2" }
--     local orm_obj = {
--         FirmwareVersion = "old_version",
--         children = { port1, port2 }
--     }

--     local captured_callback = nil
--     local mock_bus = {
--         match = function(self, signal, callback)
--             captured_callback = callback
--             return {}
--         end,
--         call = function(self, service, path, interface, method, signature, context, device_path, interfaces)
--             return { ['svc'] = { 'iface1' } }
--         end
--     }

--     local original_create_card_orm_object = c_network_adapter.collection.find
--     c_network_adapter.collection.find = function(self, q)
--         return orm_obj
--     end

--     local mgr = card_mgmt
--     mgr.bus = mock_bus
--     mgr.objects = {}
--     mgr.sig_slot = {}

--     local mock_msg = {
--         read = function(self, pattern)
--             local interface = comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE
--             local props = {
--                 FirmwareVersion = {
--                     value = function() return "new_version_1.2.3" end
--                 }
--             }
--             return interface, props
--         end
--     }

--     mgr:init_obj('/mock/path')

--     lu.assertNotNil(captured_callback, "Should capture property change callback")

--     captured_callback(mock_msg)

--     lu.assertEquals(orm_obj.FirmwareVersion, "new_version_1.2.3")
--     lu.assertEquals(port1.FirmwareVersion, "new_version_1.2.3")
--     lu.assertEquals(port2.FirmwareVersion, "new_version_1.2.3")

--     c_network_adapter.collection.find = original_create_card_orm_object
-- end

-- local function create_mock_device_obj(ospower_state)
--     return { OSPowerState = ospower_state or 0 }
-- end

-- local function create_mock_bus()
--     return {
--         call = function() return { ['/test/path'] = { 'bmc.dev.PCIeDevice' } } end,
--         match = function() return function() end end
--     }
-- end

-- local function create_mock_mdb_object()
--     return {
--         get_property = function(self, prop_name)
--             if prop_name == 'DeviceName' then
--                 return 0, 'test_device_name'
--             end
--             return -1, nil
--         end
--     }
-- end

-- local function setup_log_capture(log_calls)
--     log.notice = function(_, fmt, ...)
--         local msg = string.format(fmt, ...)
--         table.insert(log_calls, msg)
--     end
--     log.error = function(_, fmt, ...)
--         local msg = string.format(fmt, ...)
--         table.insert(log_calls, msg)
--     end
--     log.warning = function(_, fmt, ...)
--         local msg = string.format(fmt, ...)
--         table.insert(log_calls, msg)
--     end
-- end

-- local function setup_basic_mocks()
--     comm_fun.get_object_name_by_device_path = function() return 'test_obj' end
--     comm_fun.get_object_identifier_by_device_path = function() return {1, 'test_manager', 'test_chassis', 'test_position'} end
--     comm_fun.get_position_by_object_name = function() return '1' end
--     c_network_adapter.create_mdb_object = function()
--         return { children = {}, ObjectName = 'test_obj' }
--     end
--     mdb.get_object = create_mock_mdb_object
--     mdb.register_interface = function() end
--     c_factory.get_instance = function() return { create_object = function() end } end
--     c_network_adapter.collection = { find = function() return { children = {} } end }
-- end

-- local function setup_sd_bus_mocks()
--     local sd_bus = require 'sd_bus'
--     local orig_match_rule = sd_bus.MatchRule
--     local orig_property_changed = sd_bus.ObjMgrPropertiesChanged
--     sd_bus.MatchRule = { signal = function() return {} end }
--     sd_bus.ObjMgrPropertiesChanged = { name = 'test', interface = 'test' }
--     return orig_match_rule, orig_property_changed
-- end

-- local function restore_sd_bus_mocks(orig_match_rule, orig_property_changed)
--     local sd_bus = require 'sd_bus'
--     sd_bus.MatchRule = orig_match_rule
--     sd_bus.ObjMgrPropertiesChanged = orig_property_changed
-- end

-- function TestCardMgmt:test_init_os_power_state_success()
--     local mock_device_obj = create_mock_device_obj(0)
--     local captured_callback = nil
--     local log_calls = {}

--     -- 保存原始函数
--     local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--     local orig_log_notice = log.notice
--     local orig_log_error = log.error
--     local client = require 'network_adapter.client'
--     local fructl = require 'infrastructure.fructl'
--     local orig_client_callback = client.OnFruCtrlPropertiesChanged
--     local orig_fructl_status = fructl.get_power_status

--     -- 设置打桩
--     local orig_match_rule, orig_property_changed = setup_sd_bus_mocks()
--     setup_log_capture(log_calls)
--     setup_basic_mocks()

--     comm_fun.get_device_obj_by_path_interface = function() return mock_device_obj end
--     client.OnFruCtrlPropertiesChanged = function(callback) captured_callback = callback end
--     fructl.get_power_status = function() return 'ON' end

--     local mgr = card_mgmt
--     mgr.bus = create_mock_bus()
--     mgr.objects = {}

--     mgr:init_obj('/test/path')

--     lu.assertEquals(mock_device_obj.OSPowerState, 1)
--     lu.assertNotNil(captured_callback)
--     lu.assertNotEquals(#log_calls, 0)
--     local found = false
--     for _, msg in ipairs(log_calls) do
--         if string.find(msg, 'os power state set to 1') then
--             found = true
--             break
--         end
--     end
--     lu.assertTrue(found)

--     -- 还原
--     comm_fun.get_device_obj_by_path_interface = orig_get_device_obj
--     log.notice = orig_log_notice
--     log.error = orig_log_error
--     restore_sd_bus_mocks(orig_match_rule, orig_property_changed)
--     client.OnFruCtrlPropertiesChanged = orig_client_callback
--     fructl.get_power_status = orig_fructl_status
-- end

-- function TestCardMgmt:test_init_os_power_state_device_not_found()
--     local log_calls = {}

--     -- 保存原始函数
--     local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--     local orig_log_error = log.error
--     local orig_log_notice = log.notice

--     -- 设置打桩
--     local orig_match_rule, orig_property_changed = setup_sd_bus_mocks()
--     setup_log_capture(log_calls)
--     setup_basic_mocks()

--     -- 让init_os_power_state失败
--     comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--         if interface == comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE then
--             return nil -- init_os_power_state失败
--         end
--         return {}      -- 其他调用成功
--     end

--     local mgr = card_mgmt
--     mgr.bus = create_mock_bus()
--     mgr.objects = {}

--     mgr:init_obj('/test/path')

--     lu.assertNotEquals(#log_calls, 0)
--     local found = false
--     for _, msg in ipairs(log_calls) do
--         if string.find(msg, 'init_os_power_state failed') then
--             found = true
--             break
--         end
--     end
--     lu.assertTrue(found)

--     -- 还原
--     comm_fun.get_device_obj_by_path_interface = orig_get_device_obj
--     log.error = orig_log_error
--     log.notice = orig_log_notice
--     restore_sd_bus_mocks(orig_match_rule, orig_property_changed)
-- end

-- function TestCardMgmt:test_init_os_power_state_power_change_callback()
--     local mock_device_obj = create_mock_device_obj(0)
--     local captured_callback = nil
--     local log_calls = {}

--     -- 保存原始函数
--     local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--     local orig_log_notice = log.notice
--     local client = require 'network_adapter.client'
--     local fructl = require 'infrastructure.fructl'
--     local orig_client_callback = client.OnFruCtrlPropertiesChanged
--     local orig_fructl_status = fructl.get_power_status

--     -- 设置打桩
--     local orig_match_rule, orig_property_changed = setup_sd_bus_mocks()
--     setup_log_capture(log_calls)
--     setup_basic_mocks()

--     comm_fun.get_device_obj_by_path_interface = function() return mock_device_obj end
--     client.OnFruCtrlPropertiesChanged = function(self, callback) captured_callback = callback end
--     fructl.get_power_status = function() return 'OFF' end

--     local mgr = card_mgmt
--     mgr.bus = create_mock_bus()
--     mgr.objects = {}

--     mgr:init_obj('/test/path')

--     lu.assertEquals(mock_device_obj.OSPowerState, 0)
--     lu.assertNotNil(captured_callback)

--     -- 测试回调函数
--     captured_callback({ PowerState = { value = function() return 'ON' end } })
--     lu.assertEquals(mock_device_obj.OSPowerState, 1)
--     lu.assertNotNil(string.find(log_calls[#log_calls], 'os power state changed to 1'))

--     captured_callback({ PowerState = { value = function() return 'OFF' end } })
--     lu.assertEquals(mock_device_obj.OSPowerState, 0)
--     lu.assertNotNil(string.find(log_calls[#log_calls], 'os power state changed to 0'))

--     -- 还原
--     comm_fun.get_device_obj_by_path_interface = orig_get_device_obj
--     log.notice = orig_log_notice
--     restore_sd_bus_mocks(orig_match_rule, orig_property_changed)
--     client.OnFruCtrlPropertiesChanged = orig_client_callback
--     fructl.get_power_status = orig_fructl_status
-- end

-- function TestCardMgmt:test_init_os_power_state_initial_power_off()
--     local mock_device_obj = create_mock_device_obj(1)
--     local log_calls = {}

--     -- 保存原始函数
--     local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--     local orig_log_notice = log.notice
--     local client = require 'network_adapter.client'
--     local fructl = require 'infrastructure.fructl'
--     local orig_client_callback = client.OnFruCtrlPropertiesChanged
--     local orig_fructl_status = fructl.get_power_status

--     -- 设置打桩
--     local orig_match_rule, orig_property_changed = setup_sd_bus_mocks()
--     setup_log_capture(log_calls)
--     setup_basic_mocks()

--     comm_fun.get_device_obj_by_path_interface = function() return mock_device_obj end
--     client.OnFruCtrlPropertiesChanged = function() end
--     fructl.get_power_status = function() return 'OFF' end

--     local mgr = card_mgmt
--     mgr.bus = create_mock_bus()
--     mgr.objects = {}

--     mgr:init_obj('/test/path')

--     lu.assertEquals(mock_device_obj.OSPowerState, 0)
--     lu.assertNotEquals(#log_calls, 0)
--     local found = false
--     for _, msg in ipairs(log_calls) do
--         if string.find(msg, 'os power state set to 0') then
--             found = true
--             break
--         end
--     end
--     lu.assertTrue(found)

--     -- 还原
--     comm_fun.get_device_obj_by_path_interface = orig_get_device_obj
--     log.notice = orig_log_notice
--     restore_sd_bus_mocks(orig_match_rule, orig_property_changed)
--     client.OnFruCtrlPropertiesChanged = orig_client_callback
--     fructl.get_power_status = orig_fructl_status
-- end

-- function TestCardMgmt:test_get_device_name_success()
--     local mock_device_obj = { DeviceName = 'test_device_name' }
--     comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--         if interface == comm_defs.PCIE_DEVICE_INTERFACE then
--             return mock_device_obj
--         end
--         return {}
--     end

--     local mgr = card_mgmt
--     mgr.bus = create_mock_bus()
--     mgr.objects = {}
--     mgr.sig_slot = {}

--     mgr:init_obj('/test/path')

--     -- 测试通过，说明get_device_name成功执行了
--     lu.assertTrue(true)
-- end

-- function TestCardMgmt:test_get_device_name_failed()
--     local log_calls = {}

--     -- 设置打桩
--     setup_log_capture(log_calls)

--     comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--         if interface == comm_defs.PCIE_DEVICE_INTERFACE then
--             return nil -- 模拟获取失败
--         end
--         return {}      -- 其他接口返回正常对象
--     end

--     local mgr = card_mgmt
--     mgr.bus = create_mock_bus()
--     mgr.objects = {}
--     mgr.sig_slot = {}

--     mgr:init_obj('/test/path')

--     -- 验证错误日志
--     local found_error = false
--     for _, msg in ipairs(log_calls) do
--         if string.find(msg, 'get_device_name failed to get pcie device obj') then
--             found_error = true
--             break
--         end
--     end
--     lu.assertTrue(found_error, "Should log error when get_device_name fails")
-- end

-- function TestCardMgmt:test_init_component_health_failed()
--     local log_calls = {}

--     -- 设置打桩
--     setup_log_capture(log_calls)

--     comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--         if interface == comm_defs.PCIE_CARD_DEVICE_INTERFACE then
--             return nil -- 模拟init_component_health失败
--         end
--         return {}      -- 其他接口返回正常对象
--     end

--     local mgr = card_mgmt
--     mgr.bus = create_mock_bus()
--     mgr.objects = {}
--     mgr.sig_slot = {}

--     mgr:init_obj('/test/path')

--     -- 验证错误日志
--     local found_error = false
--     for _, msg in ipairs(log_calls) do
--         if string.find(msg, 'init component health failed') then
--             found_error = true
--             break
--         end
--     end
--     lu.assertTrue(found_error, "Should log error when init_component_health fails")
-- end

-- -- 测试真正的collect_log_by_smbus源代码执行路径
-- function TestCardMgmt:test_real_collect_log_by_smbus_execution()
--     local method_called = false
--     local log_calls = {}
--     local signal_callback = nil
    
--     -- 保存原始函数
--     local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--     local orig_get_object_name = comm_fun.get_object_name_by_device_path
--     local orig_mdb_get_object = mdb.get_object
--     local orig_mdb_register = mdb.register_interface
--     local c_network_adapter = require 'device.class.network_adapter'
--     local orig_create_mdb_object = c_network_adapter.create_mdb_object
--     local orig_collection_find = c_network_adapter.collection.find
--     local client = require 'network_adapter.client'
--     local orig_on_component_changed = client.OnComponentPropertiesChanged
--     local log_collector = require 'device.class.log_collector'
--     local orig_get_smbus_log_dir = log_collector.get_smbus_log_dir
--     local orig_create_dir = log_collector.create_dir
--     local orig_log_notice = log.notice
    
--     -- 设置日志捕获
--     setup_log_capture(log_calls)
--     log.notice = function(_, fmt, ...)
--         table.insert(log_calls, string.format(fmt, ...))
--     end
    
--     -- 模拟D-Bus消息对象
--     local mock_msg = {
--         read = function(self, format)
--             return comm_defs.NETWORK_ADAPTER_DEVICE_FAULT_STATUS_INTERFACE, {
--                 FaultState = { value = function() return 1 end }  -- 故障状态
--             }
--         end
--     }
    
--     -- 模拟设备对象和依赖
--     local mock_log_device_obj = {
--         call_method = function(self, method, signature, dir)
--             method_called = true
--             return true
--         end
--     }
    
--     local mock_card_orm_obj = {
--         children = {}, NetworkPortCount = 1, NodeId = 'test_node', ID = 'test_node',
--         smbus_collect_status = comm_defs.LOG_DUMP_IDLE,
--         smbus_has_collected = false
--     }
    
--     -- 模拟bus.match方法来捕获信号回调
--     local mock_bus = create_mock_bus()
--     mock_bus.match = function(self, signal_rule, callback)
--         signal_callback = callback
--         return {} -- 返回信号订阅对象
--     end
--     mock_bus.call = function() return { ['/test/path'] = { 'test_interface' } } end
    
--     -- 设置打桩
--     comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--         if interface == comm_defs.NETWORK_ADAPTER_DEVICE_LOG_COLLECTION_INTERFACE then
--             return mock_log_device_obj
--         end
--         return {}
--     end
--     comm_fun.get_object_name_by_device_path = function() return 'test_obj' end
--     comm_fun.get_position_by_object_name = function(obj_name) return '1' end
--     mdb.get_object = function() return { get_property = function() return 0, 'test_device' end } end
--     mdb.register_interface = function() end
--     c_network_adapter.create_mdb_object = function() return mock_card_orm_obj end
--     c_network_adapter.collection.find = function() return mock_card_orm_obj end
--     client.OnComponentPropertiesChanged = function() end
--     log_collector.get_smbus_log_dir = function() return '/test/smbus/dir' end
--     log_collector.create_dir = function() return true end
    
--     -- 执行init_obj创建对象并注册信号
--     local mgr = card_mgmt
--     mgr.bus = mock_bus
--     mgr.objects = {}
--     mgr.sig_slot = {}
    
--     local result = pcall(function() mgr:init_obj('/test/path') end)
    
--     -- 验证对象创建成功
--     lu.assertTrue(result, "Should successfully create card object")
--     lu.assertNotNil(signal_callback, "Should register property change signal")
    
--     -- 现在触发真正的信号处理器，这会调用源代码中的collect_log_by_smbus
--     if signal_callback then
--         signal_callback(mock_msg)
--     end
    
--     -- 验证源代码被执行
--     lu.assertTrue(method_called, "Should call CollectLogBySmbus method from source code")
--     lu.assertTrue(mock_card_orm_obj.smbus_has_collected, "Should set smbus_has_collected flag")
    
--     -- 验证日志
--     local found_log = false
--     for _, msg in ipairs(log_calls) do
--         if string.find(msg, 'collect_log_by_smbus start') then
--             found_log = true
--             break
--         end
--     end
--     lu.assertTrue(found_log, "Should log collect_log_by_smbus start message")
    
--     -- 还原打桩
--     comm_fun.get_device_obj_by_path_interface = orig_get_device_obj
--     comm_fun.get_object_name_by_device_path = orig_get_object_name
--     mdb.get_object = orig_mdb_get_object
--     mdb.register_interface = orig_mdb_register
--     c_network_adapter.create_mdb_object = orig_create_mdb_object
--     c_network_adapter.collection.find = orig_collection_find
--     client.OnComponentPropertiesChanged = orig_on_component_changed
--     log_collector.get_smbus_log_dir = orig_get_smbus_log_dir
--     log_collector.create_dir = orig_create_dir
--     log.notice = orig_log_notice
-- end

-- -- 测试BMC重启信号触发collect_log_by_smbus源代码执行
-- function TestCardMgmt:test_bmc_reset_signal_triggers_source_code()
--     local smbus_method_called = false
--     local ncsi_method_called = false
--     local log_calls = {}
--     local bmc_callback = nil
    
--     -- 保存原始函数
--     local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--     local orig_get_object_name = comm_fun.get_object_name_by_device_path
--     local orig_mdb_get_object = mdb.get_object
--     local orig_mdb_register = mdb.register_interface
--     local c_network_adapter = require 'device.class.network_adapter'
--     local orig_create_mdb_object = c_network_adapter.create_mdb_object
--     local orig_collection_find = c_network_adapter.collection.find
--     local client = require 'network_adapter.client'
--     local orig_on_component_changed = client.OnComponentPropertiesChanged
--     local log_collector = require 'device.class.log_collector'
--     local orig_get_smbus_log_dir = log_collector.get_smbus_log_dir
--     local orig_get_ncsi_log_dir = log_collector.get_ncsi_log_dir
--     local orig_create_dir = log_collector.create_dir
--     local orig_bmc_sig = log_collector.log_dump_reset_bmc_sig
--     local orig_log_notice = log.notice
    
--     -- 设置日志捕获
--     setup_log_capture(log_calls)
--     log.notice = function(_, fmt, ...)
--         table.insert(log_calls, string.format(fmt, ...))
--     end
    
--     -- 模拟设备对象
--     local mock_log_device_obj = {
--         call_method = function(self, method, signature, dir)
--             if method == 'CollectLogBySmbus' then
--                 smbus_method_called = true
--             elseif method == 'CollectLogByNcsi' then
--                 ncsi_method_called = true
--             end
--             return true
--         end
--     }
    
--     -- 关键：模拟card_orm_obj，让connect_signal能够捕获并执行callback
--     local mock_card_orm_obj = {
--         children = {}, NetworkPortCount = 1, NodeId = 'test_node', ID = 'test_node',
--         smbus_collect_status = comm_defs.LOG_DUMP_IDLE,
--         ncsi_collect_status = comm_defs.LOG_DUMP_IDLE,
--         smbus_has_collected = false,
--         connect_signal = function(self, signal, callback)
--             -- 如果是BMC重启信号，保存callback
--             if signal == log_collector.log_dump_reset_bmc_sig then
--                 bmc_callback = callback
--             end
--         end,
--         next_tick = function(self, callback)
--             -- 立即执行callback，模拟异步执行
--             callback()
--         end,
--         wait_mpu_idle = function() return true end
--     }
    
--     local mock_bus = create_mock_bus()
--     mock_bus.call = function() return { ['/test/path'] = { 'test_interface' } } end
    
--     -- 设置打桩
--     log_collector.log_dump_reset_bmc_sig = { name = 'bmc_reset' }
--     comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--         if interface == comm_defs.NETWORK_ADAPTER_DEVICE_LOG_COLLECTION_INTERFACE then
--             return mock_log_device_obj
--         end
--         return {}
--     end
--     comm_fun.get_object_name_by_device_path = function() return 'test_obj' end
--     mdb.get_object = function() return { get_property = function() return 0, 'test_device' end } end
--     mdb.register_interface = function() end
--     c_network_adapter.create_mdb_object = function() return mock_card_orm_obj end
--     c_network_adapter.collection.find = function() return mock_card_orm_obj end
--     client.ForeachComponentObjects = function() end
--     client.OnComponentInterfacesAdded = function() end
--     client.OnComponentPropertiesChanged = function() end
--     log_collector.get_smbus_log_dir = function() return '/test/smbus/dir' end
--     log_collector.get_ncsi_log_dir = function() return '/test/ncsi/dir' end
--     log_collector.create_dir = function() return true end
--     client.OnBoardInterfacesAdded = function() end
--     client.OnBoardPropertiesChanged = function() end
--     client.ForeachBoardObjects = function() end
--     client.ForeachSmBiosObjects = function() end
--     client.OnSmBiosInterfacesAdded = function() end
--     client.OnSmBiosPropertiesChanged = function() end
    
--     -- 第一步：通过init_obj调用listen_bmc_os_reset_signal注册信号
--     local mgr = card_mgmt
--     mgr.bus = mock_bus
--     mgr.objects = {}
--     mgr.sig_slot = {}
    
--     local result = pcall(function() mgr:init_obj('/test/path') end)
    
--     -- 验证对象创建和信号注册成功
--     lu.assertTrue(result, "Should successfully create card object")
--     lu.assertNotNil(bmc_callback, "Should register BMC reset signal callback")
    
--     -- 第二步：触发BMC重启信号，这会执行第195-204行的源代码
--     if bmc_callback then
--         bmc_callback()  -- 执行源代码中第195行注册的callback
--     end
    
--     -- 验证源代码被真正执行
--     lu.assertTrue(smbus_method_called, "Should call CollectLogBySmbus from source code")
--     lu.assertTrue(ncsi_method_called, "Should call CollectLogByNcsi from source code")
    
--     -- 验证日志（来自源代码第197和201行）
--     local bmc_smbus_logged = false
--     local bmc_ncsi_logged = false
--     for _, msg in ipairs(log_calls) do
--         if string.find(msg, 'receive bmc reset signal, collect log by smbus') then
--             bmc_smbus_logged = true
--         elseif string.find(msg, 'receive bmc reset signal, collect log by ncsi') then
--             bmc_ncsi_logged = true
--         end
--     end
--     lu.assertTrue(bmc_smbus_logged, "Should log BMC smbus message from source code")
--     lu.assertTrue(bmc_ncsi_logged, "Should log BMC ncsi message from source code")
    
--     -- 还原打桩
--     comm_fun.get_device_obj_by_path_interface = orig_get_device_obj
--     comm_fun.get_object_name_by_device_path = orig_get_object_name
--     mdb.get_object = orig_mdb_get_object
--     mdb.register_interface = orig_mdb_register
--     c_network_adapter.create_mdb_object = orig_create_mdb_object
--     c_network_adapter.collection.find = orig_collection_find
--     client.OnComponentPropertiesChanged = orig_on_component_changed
--     log_collector.get_smbus_log_dir = orig_get_smbus_log_dir
--     log_collector.get_ncsi_log_dir = orig_get_ncsi_log_dir
--     log_collector.create_dir = orig_create_dir
--     log_collector.log_dump_reset_bmc_sig = orig_bmc_sig
--     log.notice = orig_log_notice
-- end

-- -- 测试OS重启信号触发handle_reset_os源代码执行
-- function TestCardMgmt:test_os_reset_signal_triggers_source_code()
--     local handle_reset_called = false
--     local smbus_method_called = false
--     local log_calls = {}
--     local os_callback = nil
--     local sleep_called = false
    
--     -- 保存原始函数
--     local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--     local orig_get_object_name = comm_fun.get_object_name_by_device_path
--     local orig_mdb_get_object = mdb.get_object
--     local orig_mdb_register = mdb.register_interface
--     local c_network_adapter = require 'device.class.network_adapter'
--     local orig_create_mdb_object = c_network_adapter.create_mdb_object
--     local orig_collection_find = c_network_adapter.collection.find
--     local client = require 'network_adapter.client'
--     local orig_on_component_changed = client.OnComponentPropertiesChanged
--     local log_collector = require 'device.class.log_collector'
--     local orig_get_smbus_log_dir = log_collector.get_smbus_log_dir
--     local orig_get_ncsi_log_dir = log_collector.get_ncsi_log_dir
--     local orig_create_dir = log_collector.create_dir
--     local orig_smbios_sig = log_collector.log_dump_reset_smbios_sig
--     local orig_log_notice = log.notice
--     local skynet = require 'skynet'
--     local orig_skynet_sleep = skynet.sleep
    
--     -- 设置日志捕获
--     setup_log_capture(log_calls)
--     log.notice = function(_, fmt, ...)
--         table.insert(log_calls, string.format(fmt, ...))
--     end
    
--     skynet.sleep = function(ms)
--         sleep_called = true
--         lu.assertEquals(ms, 12000)  -- 验证睡眠时间
--     end
    
--     -- 模拟设备对象
--     local mock_reset_device_obj = {
--         call_method = function(self, method, signature)
--             if method == 'HandleOsResetSignal' then
--                 handle_reset_called = true
--             end
--             return true
--         end
--     }
    
--     local mock_log_device_obj = {
--         call_method = function(self, method, signature, dir)
--             if method == 'CollectLogBySmbus' then
--                 smbus_method_called = true
--             end
--             return true
--         end
--     }
    
--     -- 关键：模拟card_orm_obj，让connect_signal能够捕获并执行OS重启callback
--     local mock_card_orm_obj = {
--         children = {}, NetworkPortCount = 1, NodeId = 'test_node', ID = 'test_node',
--         smbus_collect_status = comm_defs.LOG_DUMP_IDLE,
--         ncsi_collect_status = comm_defs.LOG_DUMP_IDLE,
--         connect_signal = function(self, signal, callback)
--             -- 如果是OS重启信号，保存callback
--             if signal == log_collector.log_dump_reset_smbios_sig then
--                 os_callback = callback
--             end
--         end,
--         next_tick = function(self, callback)
--             callback()  -- 立即执行callback
--         end,
--         wait_mpu_idle = function() return true end  -- 添加缺失的方法
--     }
    
--     local mock_bus = create_mock_bus()
--     mock_bus.call = function() return { ['/test/path'] = { 'test_interface' } } end
    
--     -- 设置打桩
--     log_collector.log_dump_reset_smbios_sig = { name = 'smbios_reset' }
--     comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--         if interface == comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE then
--             return mock_reset_device_obj
--         elseif interface == comm_defs.NETWORK_ADAPTER_DEVICE_LOG_COLLECTION_INTERFACE then
--             return mock_log_device_obj
--         end
--         return {}
--     end
--     comm_fun.get_object_name_by_device_path = function() return 'test_obj' end
--     mdb.get_object = function() return { get_property = function() return 0, 'test_device' end } end
--     mdb.register_interface = function() end
--     c_network_adapter.create_mdb_object = function() return mock_card_orm_obj end
--     c_network_adapter.collection.find = function() return mock_card_orm_obj end
--     client.OnComponentPropertiesChanged = function() end
--     log_collector.get_smbus_log_dir = function() return '/test/smbus/dir' end
--     log_collector.get_ncsi_log_dir = function() return '/test/ncsi/dir' end
--     log_collector.create_dir = function() return true end
    
--     -- 第一步：通过init_obj注册OS重启信号
--     local mgr = card_mgmt
--     mgr.bus = mock_bus
--     mgr.objects = {}
--     mgr.sig_slot = {}
    
--     local result = pcall(function() mgr:init_obj('/test/path') end)
    
--     -- 验证对象创建和信号注册成功
--     lu.assertTrue(result, "Should successfully create card object")
--     lu.assertNotNil(os_callback, "Should register OS reset signal callback")
    
--     -- 第二步：触发OS重启信号，这会执行第206-216行的源代码
--     if os_callback then
--         os_callback()  -- 执行源代码中第206行注册的callback
--     end
    
--     -- 验证源代码被真正执行
--     lu.assertTrue(handle_reset_called, "Should call HandleOsResetSignal from source code")
--     lu.assertTrue(sleep_called, "Should call skynet.sleep from source code")
--     lu.assertTrue(smbus_method_called, "Should call CollectLogBySmbus from source code")
    
--     -- 验证日志（来自源代码第178和211行）
--     local handle_reset_logged = false
--     local os_smbus_logged = false
--     for _, msg in ipairs(log_calls) do
--         if string.find(msg, 'handle_reset_os, device_path is') then
--             handle_reset_logged = true
--         elseif string.find(msg, 'receive os reset signal, collect log by smbus') then
--             os_smbus_logged = true
--         end
--     end
--     lu.assertTrue(handle_reset_logged, "Should log handle_reset_os message from source code")
--     lu.assertTrue(os_smbus_logged, "Should log OS smbus message from source code")
    
--     -- 还原打桩
--     comm_fun.get_device_obj_by_path_interface = orig_get_device_obj
--     comm_fun.get_object_name_by_device_path = orig_get_object_name
--     mdb.get_object = orig_mdb_get_object
--     mdb.register_interface = orig_mdb_register
--     c_network_adapter.create_mdb_object = orig_create_mdb_object
--     c_network_adapter.collection.find = orig_collection_find
--     client.OnComponentPropertiesChanged = orig_on_component_changed
--     log_collector.get_smbus_log_dir = orig_get_smbus_log_dir
--     log_collector.get_ncsi_log_dir = orig_get_ncsi_log_dir
--     log_collector.create_dir = orig_create_dir
--     log_collector.log_dump_reset_smbios_sig = orig_smbios_sig
--     log.notice = orig_log_notice
--     skynet.sleep = orig_skynet_sleep
-- end

-- -- 通用异常分支测试框架 - get_log_by_smbus
-- function TestCardMgmt:test_get_log_by_smbus_exception_branches()
--     local test_cases = {
--         {
--             name = "device_obj_nil",
--             setup = function()
--                 local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--                 comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--                     if interface == comm_defs.NETWORK_ADAPTER_DEVICE_LOG_COLLECTION_INTERFACE then
--                         return nil
--                     end
--                     return {}
--                 end
--                 return { orig_get_device_obj = orig_get_device_obj }
--             end,
--             teardown = function(saved)
--                 comm_fun.get_device_obj_by_path_interface = saved.orig_get_device_obj
--             end,
--             expected_error = "get_log_by_smbus failed, device_obj is nil"
--         },
--         {
--             name = "log_dir_nil", 
--             setup = function()
--                 local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--                 local log_collector = require 'device.class.log_collector'
--                 local orig_get_smbus_log_dir = log_collector.get_smbus_log_dir
                
--                 comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--                     if interface == comm_defs.NETWORK_ADAPTER_DEVICE_LOG_COLLECTION_INTERFACE then
--                         return {}
--                     end
--                     return {}
--                 end
--                 log_collector.get_smbus_log_dir = function() return nil end
                
--                 return { 
--                     orig_get_device_obj = orig_get_device_obj,
--                     orig_get_smbus_log_dir = orig_get_smbus_log_dir
--                 }
--             end,
--             teardown = function(saved)
--                 comm_fun.get_device_obj_by_path_interface = saved.orig_get_device_obj
--                 local log_collector = require 'device.class.log_collector'
--                 log_collector.get_smbus_log_dir = saved.orig_get_smbus_log_dir
--             end,
--             expected_error = "get_log_by_smbus failed, log_dir is nil"
--         },
--         {
--             name = "create_dir_failed",
--             setup = function()
--                 local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--                 local log_collector = require 'device.class.log_collector'
--                 local orig_get_smbus_log_dir = log_collector.get_smbus_log_dir
--                 local orig_create_dir = log_collector.create_dir
                
--                 comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--                     if interface == comm_defs.NETWORK_ADAPTER_DEVICE_LOG_COLLECTION_INTERFACE then
--                         return {}
--                     end
--                     return {}
--                 end
--                 log_collector.get_smbus_log_dir = function() return '/test/dir' end
--                 log_collector.create_dir = function() return false end
                
--                 return {
--                     orig_get_device_obj = orig_get_device_obj,
--                     orig_get_smbus_log_dir = orig_get_smbus_log_dir,
--                     orig_create_dir = orig_create_dir
--                 }
--             end,
--             teardown = function(saved)
--                 comm_fun.get_device_obj_by_path_interface = saved.orig_get_device_obj
--                 local log_collector = require 'device.class.log_collector'
--                 log_collector.get_smbus_log_dir = saved.orig_get_smbus_log_dir
--                 log_collector.create_dir = saved.orig_create_dir
--             end,
--             expected_error = "get_log_by_smbus failed, create log_dir failed"
--         },
--         {
--             name = "call_method_exception",
--             setup = function()
--                 local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--                 local log_collector = require 'device.class.log_collector'
--                 local orig_get_smbus_log_dir = log_collector.get_smbus_log_dir
--                 local orig_create_dir = log_collector.create_dir
                
--                 local mock_device_obj = {
--                     call_method = function() error("test exception") end
--                 }
--                 comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--                     if interface == comm_defs.NETWORK_ADAPTER_DEVICE_LOG_COLLECTION_INTERFACE then
--                         return mock_device_obj
--                     end
--                     return {}
--                 end
--                 log_collector.get_smbus_log_dir = function() return '/test/dir' end
--                 log_collector.create_dir = function() return true end
                
--                 return {
--                     orig_get_device_obj = orig_get_device_obj,
--                     orig_get_smbus_log_dir = orig_get_smbus_log_dir,
--                     orig_create_dir = orig_create_dir
--                 }
--             end,
--             teardown = function(saved)
--                 comm_fun.get_device_obj_by_path_interface = saved.orig_get_device_obj
--                 local log_collector = require 'device.class.log_collector'
--                 log_collector.get_smbus_log_dir = saved.orig_get_smbus_log_dir
--                 log_collector.create_dir = saved.orig_create_dir
--             end,
--             expected_error = "get_log_by_smbus failed, err is"
--         },
--         {
--             name = "call_method_returns_false",
--             setup = function()
--                 local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--                 local log_collector = require 'device.class.log_collector'
--                 local orig_get_smbus_log_dir = log_collector.get_smbus_log_dir
--                 local orig_create_dir = log_collector.create_dir
                
--                 local mock_device_obj = {
--                     call_method = function() return false end
--                 }
--                 comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--                     if interface == comm_defs.NETWORK_ADAPTER_DEVICE_LOG_COLLECTION_INTERFACE then
--                         return mock_device_obj
--                     end
--                     return {}
--                 end
--                 log_collector.get_smbus_log_dir = function() return '/test/dir' end
--                 log_collector.create_dir = function() return true end
                
--                 return {
--                     orig_get_device_obj = orig_get_device_obj,
--                     orig_get_smbus_log_dir = orig_get_smbus_log_dir,
--                     orig_create_dir = orig_create_dir
--                 }
--             end,
--             teardown = function(saved)
--                 comm_fun.get_device_obj_by_path_interface = saved.orig_get_device_obj
--                 local log_collector = require 'device.class.log_collector'
--                 log_collector.get_smbus_log_dir = saved.orig_get_smbus_log_dir
--                 log_collector.create_dir = saved.orig_create_dir
--             end,
--             expected_error = "get_log_by_smbus failed, device_path is"
--         }
--     }

--     for _, test_case in ipairs(test_cases) do
--         local log_calls = {}
--         setup_log_capture(log_calls)
--         local signal_callback = nil
        
--         -- 基础打桩设置
--         local orig_get_object_name = comm_fun.get_object_name_by_device_path
--         local orig_mdb_get_object = mdb.get_object
--         local orig_mdb_register = mdb.register_interface
--         local c_network_adapter = require 'device.class.network_adapter'
--         local orig_create_mdb_object = c_network_adapter.create_mdb_object
--         local orig_collection_find = c_network_adapter.collection.find
--         local client = require 'network_adapter.client'
--         local orig_on_component_changed = client.OnComponentPropertiesChanged
        
--         local mock_card_orm_obj = {
--             children = {}, NetworkPortCount = 1, NodeId = 'test_node', ID = 'test_node',
--             smbus_collect_status = comm_defs.LOG_DUMP_IDLE,
--             smbus_has_collected = false
--         }
        
--         -- 模拟bus.match方法来捕获信号回调
--         local mock_bus = create_mock_bus()
--         mock_bus.match = function(self, signal_rule, callback)
--             signal_callback = callback
--             return {}
--         end
--         mock_bus.call = function() return { ['/test/path'] = { 'test_interface' } } end
        
--         -- 基础打桩
--         comm_fun.get_device_obj_by_path_interface = function() return {} end
--         comm_fun.get_object_name_by_device_path = function() return 'test_obj' end
--         mdb.get_object = function() return { get_property = function() return 0, 'test_device' end } end
--         mdb.register_interface = function() end
--         c_network_adapter.create_mdb_object = function() return mock_card_orm_obj end
--         c_network_adapter.collection.find = function() return mock_card_orm_obj end
--         client.OnComponentPropertiesChanged = function() end
        
--         -- 执行init_obj创建对象并注册信号
--         local mgr = card_mgmt
--         mgr.bus = mock_bus
--         mgr.objects = {}
--         mgr.sig_slot = {}
        
--         local result = pcall(function() mgr:init_obj('/test/path') end)
--         lu.assertTrue(result, "Should successfully create card object for " .. test_case.name)
--         lu.assertNotNil(signal_callback, "Should register property change signal for " .. test_case.name)
        
--         -- 在callback执行前设置测试特定的异常条件
--         local saved = test_case.setup()
        
--         -- 模拟D-Bus消息对象并触发回调
--         local mock_msg = {
--             read = function(self, format)
--                 return comm_defs.NETWORK_ADAPTER_DEVICE_FAULT_STATUS_INTERFACE, {
--                     FaultState = { value = function() return 1 end }
--                 }
--             end
--         }
        
--         -- 触发信号处理器，这时会使用刚设置的异常条件
--         if signal_callback then
--             signal_callback(mock_msg)
--         end
        
--         -- 验证预期的错误日志
--         local found_error = false
--         for _, msg in ipairs(log_calls) do
--             if string.find(msg, test_case.expected_error) then
--                 found_error = true
--                 break
--             end
--         end
--         lu.assertTrue(found_error, "Should log expected error for " .. test_case.name .. ": " .. test_case.expected_error)
        
--         -- 清理测试特定的打桩
--         test_case.teardown(saved)
        
--         -- 还原基础打桩
--         comm_fun.get_object_name_by_device_path = orig_get_object_name
--         mdb.get_object = orig_mdb_get_object
--         mdb.register_interface = orig_mdb_register
--         c_network_adapter.create_mdb_object = orig_create_mdb_object
--         c_network_adapter.collection.find = orig_collection_find
--         client.OnComponentPropertiesChanged = orig_on_component_changed
--     end
-- end

-- -- 通用异常分支测试框架 - get_log_by_ncsi
-- function TestCardMgmt:test_get_log_by_ncsi_exception_branches()
--     local test_cases = {
--         {
--             name = "device_obj_nil",
--             setup = function()
--                 local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--                 comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--                     if interface == comm_defs.NETWORK_ADAPTER_DEVICE_LOG_COLLECTION_INTERFACE then
--                         return nil
--                     end
--                     return {}
--                 end
--                 return { orig_get_device_obj = orig_get_device_obj }
--             end,
--             teardown = function(saved)
--                 comm_fun.get_device_obj_by_path_interface = saved.orig_get_device_obj
--             end,
--             expected_error = "get_log_by_ncsi failed, device_obj is nil"
--         },
--         {
--             name = "mpu_not_available",
--             setup = function()
--                 local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--                 comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--                     if interface == comm_defs.NETWORK_ADAPTER_DEVICE_LOG_COLLECTION_INTERFACE then
--                         return {}
--                     end
--                     return {}
--                 end
--                 return { orig_get_device_obj = orig_get_device_obj }
--             end,
--             teardown = function(saved)
--                 comm_fun.get_device_obj_by_path_interface = saved.orig_get_device_obj
--             end,
--             expected_error = "mpu is not available, device_path is"
--         },
--         {
--             name = "log_dir_nil",
--             setup = function()
--                 local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--                 local log_collector = require 'device.class.log_collector'
--                 local orig_get_ncsi_log_dir = log_collector.get_ncsi_log_dir
                
--                 comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--                     if interface == comm_defs.NETWORK_ADAPTER_DEVICE_LOG_COLLECTION_INTERFACE then
--                         return {}
--                     end
--                     return {}
--                 end
--                 log_collector.get_ncsi_log_dir = function() return nil end
                
--                 return {
--                     orig_get_device_obj = orig_get_device_obj,
--                     orig_get_ncsi_log_dir = orig_get_ncsi_log_dir
--                 }
--             end,
--             teardown = function(saved)
--                 comm_fun.get_device_obj_by_path_interface = saved.orig_get_device_obj
--                 local log_collector = require 'device.class.log_collector'
--                 log_collector.get_ncsi_log_dir = saved.orig_get_ncsi_log_dir
--             end,
--             expected_error = "get_log_by_ncsi failed, log_dir is nil"
--         },
--         {
--             name = "create_dir_failed",
--             setup = function()
--                 local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--                 local log_collector = require 'device.class.log_collector'
--                 local orig_get_ncsi_log_dir = log_collector.get_ncsi_log_dir
--                 local orig_create_dir = log_collector.create_dir
                
--                 comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--                     if interface == comm_defs.NETWORK_ADAPTER_DEVICE_LOG_COLLECTION_INTERFACE then
--                         return {}
--                     end
--                     return {}
--                 end
--                 log_collector.get_ncsi_log_dir = function() return '/test/dir' end
--                 log_collector.create_dir = function() return false end
                
--                 return {
--                     orig_get_device_obj = orig_get_device_obj,
--                     orig_get_ncsi_log_dir = orig_get_ncsi_log_dir,
--                     orig_create_dir = orig_create_dir
--                 }
--             end,
--             teardown = function(saved)
--                 comm_fun.get_device_obj_by_path_interface = saved.orig_get_device_obj
--                 local log_collector = require 'device.class.log_collector'
--                 log_collector.get_ncsi_log_dir = saved.orig_get_ncsi_log_dir
--                 log_collector.create_dir = saved.orig_create_dir
--             end,
--             expected_error = "get_log_by_ncsi failed, create log_dir failed"
--         },
--         {
--             name = "call_method_exception",
--             setup = function()
--                 local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--                 local log_collector = require 'device.class.log_collector'
--                 local orig_get_ncsi_log_dir = log_collector.get_ncsi_log_dir
--                 local orig_create_dir = log_collector.create_dir
                
--                 local mock_device_obj = {
--                     call_method = function() error("test exception") end
--                 }
--                 comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--                     if interface == comm_defs.NETWORK_ADAPTER_DEVICE_LOG_COLLECTION_INTERFACE then
--                         return mock_device_obj
--                     end
--                     return {}
--                 end
--                 log_collector.get_ncsi_log_dir = function() return '/test/dir' end
--                 log_collector.create_dir = function() return true end
                
--                 return {
--                     orig_get_device_obj = orig_get_device_obj,
--                     orig_get_ncsi_log_dir = orig_get_ncsi_log_dir,
--                     orig_create_dir = orig_create_dir
--                 }
--             end,
--             teardown = function(saved)
--                 comm_fun.get_device_obj_by_path_interface = saved.orig_get_device_obj
--                 local log_collector = require 'device.class.log_collector'
--                 log_collector.get_ncsi_log_dir = saved.orig_get_ncsi_log_dir
--                 log_collector.create_dir = saved.orig_create_dir
--             end,
--             expected_error = "get_log_by_ncsi failed, err is"
--         },
--         {
--             name = "call_method_returns_false",
--             setup = function()
--                 local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--                 local log_collector = require 'device.class.log_collector'
--                 local orig_get_ncsi_log_dir = log_collector.get_ncsi_log_dir
--                 local orig_create_dir = log_collector.create_dir
                
--                 local mock_device_obj = {
--                     call_method = function() return false end
--                 }
--                 comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--                     if interface == comm_defs.NETWORK_ADAPTER_DEVICE_LOG_COLLECTION_INTERFACE then
--                         return mock_device_obj
--                     end
--                     return {}
--                 end
--                 log_collector.get_ncsi_log_dir = function() return '/test/dir' end
--                 log_collector.create_dir = function() return true end
                
--                 return {
--                     orig_get_device_obj = orig_get_device_obj,
--                     orig_get_ncsi_log_dir = orig_get_ncsi_log_dir,
--                     orig_create_dir = orig_create_dir
--                 }
--             end,
--             teardown = function(saved)
--                 comm_fun.get_device_obj_by_path_interface = saved.orig_get_device_obj
--                 local log_collector = require 'device.class.log_collector'
--                 log_collector.get_ncsi_log_dir = saved.orig_get_ncsi_log_dir
--                 log_collector.create_dir = saved.orig_create_dir
--             end,
--             expected_error = "get_log_by_ncsi failed, device_path is"
--         }
--     }

--     for _, test_case in ipairs(test_cases) do
--         local log_calls = {}
--         setup_log_capture(log_calls)
--         local bmc_callback = nil
        
--         -- 基础打桩设置
--         local orig_get_object_name = comm_fun.get_object_name_by_device_path
--         local orig_mdb_get_object = mdb.get_object
--         local orig_mdb_register = mdb.register_interface
--         local c_network_adapter = require 'device.class.network_adapter'
--         local orig_create_mdb_object = c_network_adapter.create_mdb_object
--         local orig_collection_find = c_network_adapter.collection.find
--         local client = require 'network_adapter.client'
--         local orig_on_component_changed = client.OnComponentPropertiesChanged
--         local log_collector = require 'device.class.log_collector'
--         local orig_get_smbus_log_dir = log_collector.get_smbus_log_dir
--         local orig_get_ncsi_log_dir = log_collector.get_ncsi_log_dir
--         local orig_create_dir = log_collector.create_dir
--         local orig_bmc_sig = log_collector.log_dump_reset_bmc_sig
        
--         local mock_card_orm_obj = {
--             children = {}, NetworkPortCount = 1, NodeId = 'test_node', ID = 'test_node',
--             smbus_collect_status = comm_defs.LOG_DUMP_IDLE,
--             ncsi_collect_status = comm_defs.LOG_DUMP_IDLE,
--             connect_signal = function(self, signal, callback)
--                 if signal == log_collector.log_dump_reset_bmc_sig then
--                     bmc_callback = callback
--                 end
--             end,
--             next_tick = function(self, callback) callback() end,
--             wait_mpu_idle = function() 
--                 -- 根据测试用例返回不同的值
--                 if test_case.name == "mpu_not_available" then
--                     return false
--                 else
--                     return true
--                 end
--             end
--         }
        
--         local mock_bus = create_mock_bus()
--         mock_bus.call = function() return { ['/test/path'] = { 'test_interface' } } end
        
--         -- 基础打桩
--         log_collector.log_dump_reset_bmc_sig = { name = 'bmc_reset' }
--         comm_fun.get_device_obj_by_path_interface = function() return {} end
--         comm_fun.get_object_name_by_device_path = function() return 'test_obj' end
--         mdb.get_object = function() return { get_property = function() return 0, 'test_device' end } end
--         mdb.register_interface = function() end
--         c_network_adapter.create_mdb_object = function() return mock_card_orm_obj end
--         c_network_adapter.collection.find = function() return mock_card_orm_obj end
--         client.OnComponentPropertiesChanged = function() end
--         log_collector.get_smbus_log_dir = function() return '/test/smbus/dir' end
--         log_collector.get_ncsi_log_dir = function() return '/test/ncsi/dir' end
--         log_collector.create_dir = function() return true end
        
--         -- 执行init_obj创建对象并注册信号
--         local mgr = card_mgmt
--         mgr.bus = mock_bus
--         mgr.objects = {}
--         mgr.sig_slot = {}
        
--         local result = pcall(function() mgr:init_obj('/test/path') end)
--         lu.assertTrue(result, "Should successfully create card object for " .. test_case.name)
--         lu.assertNotNil(bmc_callback, "Should register BMC reset signal for " .. test_case.name)
        
--         -- 在callback执行前设置测试特定的异常条件
--         local saved = test_case.setup()
        
--         -- 触发BMC重启信号，这会调用collect_log_by_ncsi -> get_log_by_ncsi
--         if bmc_callback then
--             bmc_callback()
--         end
        
--         -- 验证预期的错误日志
--         local found_error = false
--         for _, msg in ipairs(log_calls) do
--             if string.find(msg, test_case.expected_error) then
--                 found_error = true
--                 break
--             end
--         end
--         lu.assertTrue(found_error, "Should log expected error for " .. test_case.name .. ": " .. test_case.expected_error)
        
--         -- 清理测试特定的打桩
--         test_case.teardown(saved)
        
--         -- 还原基础打桩
--         comm_fun.get_object_name_by_device_path = orig_get_object_name
--         mdb.get_object = orig_mdb_get_object
--         mdb.register_interface = orig_mdb_register
--         c_network_adapter.create_mdb_object = orig_create_mdb_object
--         c_network_adapter.collection.find = orig_collection_find
--         client.OnComponentPropertiesChanged = orig_on_component_changed
--         log_collector.get_smbus_log_dir = orig_get_smbus_log_dir
--         log_collector.get_ncsi_log_dir = orig_get_ncsi_log_dir
--         log_collector.create_dir = orig_create_dir
--         log_collector.log_dump_reset_bmc_sig = orig_bmc_sig
--     end
-- end

-- -- 测试 init_smbios_status 函数 - 成功场景
-- function TestCardMgmt:test_init_smbios_status_success()
--     local mock_card_device_obj = { SmBiosStatus = 0 }
--     local log_calls = {}
--     local on_smbios_interfaces_added_cb = nil
--     local on_smbios_properties_changed_cb = nil

--     -- 保存原始函数
--     local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--     local orig_log_notice = log.notice
--     local orig_log_error = log.error
--     local client = require 'network_adapter.client'
--     local orig_on_smbios_interfaces_added = client.OnSmBiosInterfacesAdded
--     local orig_on_smbios_properties_changed = client.OnSmBiosPropertiesChanged
--     local orig_get_smbios_objects = client.GetSmBiosObjects
--     local orig_foreach_smbios = client.ForeachSmBiosObjects

--     -- 设置打桩
--     setup_log_capture(log_calls)
--     setup_basic_mocks()

--     comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--         if interface == comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE then
--             return mock_card_device_obj
--         end
--         return {}
--     end

--     client.OnSmBiosInterfacesAdded = function(self, callback)
--         on_smbios_interfaces_added_cb = callback
--     end

--     client.OnSmBiosPropertiesChanged = function(self, callback)
--         on_smbios_properties_changed_cb = callback
--     end

--     local mock_smbios_obj = { SmBiosStatus = 3 }
--     -- 现网实现使用 ForeachSmBiosObjects 回调遍历 smbios 对象
--     client.ForeachSmBiosObjects = function(self, callback)
--         callback(mock_smbios_obj)
--     end

--     local mgr = card_mgmt
--     mgr.bus = create_mock_bus()
--     mgr.objects = {}
--     mgr.sig_slot = {}

--     -- 通过 init_obj 调用 init_smbios_status
--     mgr:init_obj('/test/path')

--     -- 验证 SmBiosStatus 被设置
--     lu.assertEquals(mock_card_device_obj.SmBiosStatus, 3)

--     -- 验证回调被注册
--     lu.assertNotNil(on_smbios_interfaces_added_cb, "Should register OnSmBiosInterfacesAdded callback")
--     lu.assertNotNil(on_smbios_properties_changed_cb, "Should register OnSmBiosPropertiesChanged callback")

--     -- 测试 OnSmBiosInterfacesAdded 回调
--     local props = {
--         SmBiosStatus = {
--             value = function() return 1 end
--         }
--     }
--     on_smbios_interfaces_added_cb(nil, nil, props)
--     lu.assertEquals(mock_card_device_obj.SmBiosStatus, 1)

--     -- 测试 OnSmBiosPropertiesChanged 回调
--     local values = {
--         SmBiosStatus = {
--             value = function() return 2 end
--         }
--     }
--     on_smbios_properties_changed_cb(values, nil, nil)
--     lu.assertEquals(mock_card_device_obj.SmBiosStatus, 2)

--     -- 验证日志
--     local found_log = false
--     for _, msg in ipairs(log_calls) do
--         if string.find(msg, 'smbios status changed to 3') then
--             found_log = true
--             break
--         end
--     end
--     lu.assertTrue(found_log, "Should log smbios status change")

--     -- 还原打桩
--     comm_fun.get_device_obj_by_path_interface = orig_get_device_obj
--     log.notice = orig_log_notice
--     log.error = orig_log_error
--     client.OnSmBiosInterfacesAdded = orig_on_smbios_interfaces_added
--     client.OnSmBiosPropertiesChanged = orig_on_smbios_properties_changed
--     client.GetSmBiosObjects = orig_get_smbios_objects
--     client.ForeachSmBiosObjects = orig_foreach_smbios
-- end

-- -- 测试 init_smbios_status 函数 - card_device_obj 为 nil
-- function TestCardMgmt:test_init_smbios_status_device_obj_nil()
--     local log_calls = {}

--     -- 保存原始函数
--     local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--     local orig_log_error = log.error

--     -- 设置打桩
--     setup_log_capture(log_calls)
--     setup_basic_mocks()

--     comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--         if interface == comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE then
--             return nil  -- 模拟获取失败
--         end
--         return {}
--     end

--     local mgr = card_mgmt
--     mgr.bus = create_mock_bus()
--     mgr.objects = {}
--     mgr.sig_slot = {}

--     mgr:init_obj('/test/path')

--     -- 验证错误日志
--     local found_error = false
--     for _, msg in ipairs(log_calls) do
--         if string.find(msg, 'init_smbios_status failed, device_path is') then
--             found_error = true
--             break
--         end
--     end
--     lu.assertTrue(found_error, "Should log error when card_device_obj is nil")

--     -- 还原打桩
--     comm_fun.get_device_obj_by_path_interface = orig_get_device_obj
--     log.error = orig_log_error
-- end

-- -- 测试 init_smbios_status 函数 - GetSmBiosObjects 返回空列表
-- function TestCardMgmt:test_init_smbios_status_empty_smbios_list()
--     local mock_card_device_obj = { SmBiosStatus = 0 }
--     local log_calls = {}

--     -- 保存原始函数
--     local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--     local client = require 'network_adapter.client'
--     local orig_on_smbios_interfaces_added = client.OnSmBiosInterfacesAdded
--     local orig_on_smbios_properties_changed = client.OnSmBiosPropertiesChanged
--     local orig_get_smbios_objects = client.GetSmBiosObjects

--     -- 设置打桩
--     setup_log_capture(log_calls)
--     setup_basic_mocks()

--     comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--         if interface == comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE then
--             return mock_card_device_obj
--         end
--         return {}
--     end

--     client.OnSmBiosInterfacesAdded = function(self, callback) end
--     client.OnSmBiosPropertiesChanged = function(self, callback) end
--     client.GetSmBiosObjects = function(self) return {} end  -- 返回空列表

--     local mgr = card_mgmt
--     mgr.bus = create_mock_bus()
--     mgr.objects = {}
--     mgr.sig_slot = {}

--     mgr:init_obj('/test/path')

--     -- 验证 SmBiosStatus 没有被改变（保持初始值）
--     lu.assertEquals(mock_card_device_obj.SmBiosStatus, 0)

--     -- 还原打桩
--     comm_fun.get_device_obj_by_path_interface = orig_get_device_obj
--     client.OnSmBiosInterfacesAdded = orig_on_smbios_interfaces_added
--     client.OnSmBiosPropertiesChanged = orig_on_smbios_properties_changed
--     client.GetSmBiosObjects = orig_get_smbios_objects
-- end

-- -- 测试 init_smbios_status 函数 - OnSmBiosPropertiesChanged 回调中 values.SmBiosStatus 为 nil
-- function TestCardMgmt:test_init_smbios_status_properties_changed_no_smbiosstatus()
--     local mock_card_device_obj = { SmBiosStatus = 3 }
--     local on_smbios_properties_changed_cb = nil

--     -- 保存原始函数
--     local orig_get_device_obj = comm_fun.get_device_obj_by_path_interface
--     local client = require 'network_adapter.client'
--     local orig_on_smbios_interfaces_added = client.OnSmBiosInterfacesAdded
--     local orig_on_smbios_properties_changed = client.OnSmBiosPropertiesChanged
--     local orig_get_smbios_objects = client.GetSmBiosObjects

--     -- 设置打桩
--     setup_basic_mocks()

--     comm_fun.get_device_obj_by_path_interface = function(bus, device_path, interface)
--         if interface == comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE then
--             return mock_card_device_obj
--         end
--         return {}
--     end

--     client.OnSmBiosInterfacesAdded = function(self, callback) end
--     client.OnSmBiosPropertiesChanged = function(self, callback)
--         on_smbios_properties_changed_cb = callback
--     end
--     client.GetSmBiosObjects = function(self) return {} end

--     local mgr = card_mgmt
--     mgr.bus = create_mock_bus()
--     mgr.objects = {}
--     mgr.sig_slot = {}

--     mgr:init_obj('/test/path')

--     -- 验证回调被注册
--     lu.assertNotNil(on_smbios_properties_changed_cb, "Should register OnSmBiosPropertiesChanged callback")

--     -- 测试回调，values.SmBiosStatus 为 nil
--     local values = {}  -- 没有 SmBiosStatus
--     on_smbios_properties_changed_cb(values, nil, nil)

--     -- 验证 SmBiosStatus 没有被改变（保持原值）
--     lu.assertEquals(mock_card_device_obj.SmBiosStatus, 3)

--     -- 还原打桩
--     comm_fun.get_device_obj_by_path_interface = orig_get_device_obj
--     client.OnSmBiosInterfacesAdded = orig_on_smbios_interfaces_added
--     client.OnSmBiosPropertiesChanged = orig_on_smbios_properties_changed
--     client.GetSmBiosObjects = orig_get_smbios_objects
-- end

-- function TestCardMgmt:test_del_obj_remove_card()
--     local mgr = card_mgmt
--     mgr.objects = { ['/mock/card'] = { id = 1 } }

--     local removed_obj
--     local orig_del = c_network_adapter.collection.del_object
--     c_network_adapter.collection.del_object = function(_, obj)
--         removed_obj = obj
--     end

--     mgr:del_obj('/mock/card')

--     lu.assertEquals(removed_obj.id, 1)
--     lu.assertNil(mgr.objects['/mock/card'])

--     c_network_adapter.collection.del_object = orig_del
-- end

local function setup_init_obj_stubs_for_network_port_count(bus, network_port_count_val)
    network_port_count_val = network_port_count_val or 4
    local client = require 'network_adapter.client'
    local fructl = require 'infrastructure.fructl'
    local log_collector = require 'device.class.log_collector'
    local setup_origs = {
        client_OnFruCtrlInterfacesAdded = client.OnFruCtrlInterfacesAdded,
        client_OnFruCtrlPropertiesChanged = client.OnFruCtrlPropertiesChanged,
        client_OnSmBiosInterfacesAdded = client.OnSmBiosInterfacesAdded,
        client_OnSmBiosPropertiesChanged = client.OnSmBiosPropertiesChanged,
        client_GetSmBiosObjects = client.GetSmBiosObjects,
        client_ForeachSmBiosObjects = client.ForeachSmBiosObjects,
        client_OnComponentInterfacesAdded = client.OnComponentInterfacesAdded,
        client_OnComponentPropertiesChanged = client.OnComponentPropertiesChanged,
        client_ForeachComponentObjects = client.ForeachComponentObjects,
        fructl_get_power_status = fructl.get_power_status,
        log_collector_log_dump_reset_bmc_sig = log_collector.log_dump_reset_bmc_sig,
        log_collector_log_dump_reset_smbios_sig = log_collector.log_dump_reset_smbios_sig,
    }
    bus.call = function(self, svc, path, iface, method, sig, ctx_arg, device_path, interfaces)
        if method == 'GetObject' then
            -- get_node_id_by_device_path 只传单元素 { PCIeDevice }；synchronize_property 传完整 device_interface_list
            if interfaces and #interfaces == 1 and interfaces[1] == comm_defs.PCIE_DEVICE_INTERFACE then
                return { ['maca_svc'] = { comm_defs.PCIE_DEVICE_INTERFACE } }
            end
            return { ['maca_svc'] = { comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE } }
        end
        if method == 'GetAll' then
            return { NetworkPortCount = true }
        end
        return {}
    end
    bus.match = function() return {} end
    comm_fun.get_object_name_by_device_path = function() return 'TestObjectName' end
    comm_fun.get_object_identifier_by_device_path = function() return { 1, 'mgr', 'chassis', 'pos' } end
    comm_fun.set_interface_add_signal = function() end
    ctx.get_context_or_default = function() return {} end
    mdb.register_interface = function() end
    mdb.get_object = function(_, device_path, interface)
        return {
            get_property = function(_, prop)
                if prop == 'DeviceName' then
                    return 0, 'NodeId_Test'
                end
                if interface == comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE and prop == 'NetworkPortCount' then
                    return 0, network_port_count_val
                end
                return -1, nil
            end
        }
    end
    c_network_adapter.create_mdb_object = function(tbl) return tbl end
    c_factory.get_instance = function() return { create_object = function() end } end
    card_init.init = function() end
    client.OnFruCtrlInterfacesAdded = function() end
    client.OnFruCtrlPropertiesChanged = function() end
    client.OnSmBiosInterfacesAdded = function() end
    client.OnSmBiosPropertiesChanged = function() end
    client.GetSmBiosObjects = function() return {} end
    client.ForeachSmBiosObjects = function() end
    client.OnComponentInterfacesAdded = function() end
    client.OnComponentPropertiesChanged = function() end
    client.ForeachComponentObjects = function() end
    fructl.get_power_status = function() return 'ON' end
    log_collector.log_dump_reset_bmc_sig = {}
    log_collector.log_dump_reset_smbios_sig = {}
    return setup_origs
end

-- 还原 handle_port_count_mismatch 相关桩（调用方负责保存 orig）
local function restore_handle_port_count_mismatch_stubs(origs)
    if origs.preload_find then
        c_network_adapter_preload.collection.find = origs.preload_find
    end
    if origs.get_instance then
        c_object_manage.get_instance = origs.get_instance
    end
    if origs.get_device_obj then
        comm_fun.get_device_obj_by_path_interface = origs.get_device_obj
    end
    if origs.get_object_name then
        comm_fun.get_object_name_by_device_path = origs.get_object_name
    end
    if origs.get_object_identifier then
        comm_fun.get_object_identifier_by_device_path = origs.get_object_identifier
    end
    if origs.set_interface_add_signal then
        comm_fun.set_interface_add_signal = origs.set_interface_add_signal
    end
    if origs.ctx_get_context then
        ctx.get_context_or_default = origs.ctx_get_context
    end
    if origs.mdb_register then
        mdb.register_interface = origs.mdb_register
    end
    if origs.mdb_get_object then
        mdb.get_object = origs.mdb_get_object
    end
    if origs.create_mdb_object then
        c_network_adapter.create_mdb_object = origs.create_mdb_object
    end
    if origs.factory_get_instance then
        c_factory.get_instance = origs.factory_get_instance
    end
    if origs.card_init_init then
        card_init.init = origs.card_init_init
    end
    if origs.log_error then
        log.error = origs.log_error
    end
    if origs.log_notice then
        log.notice = origs.log_notice
    end
    -- client / fructl / log_collector 还原
    local client = require 'network_adapter.client'
    local fructl = require 'infrastructure.fructl'
    local log_collector = require 'device.class.log_collector'
    if origs.client_OnFruCtrlInterfacesAdded then client.OnFruCtrlInterfacesAdded = origs.client_OnFruCtrlInterfacesAdded end
    if origs.client_OnFruCtrlPropertiesChanged then client.OnFruCtrlPropertiesChanged = origs.client_OnFruCtrlPropertiesChanged end
    if origs.client_OnSmBiosInterfacesAdded then client.OnSmBiosInterfacesAdded = origs.client_OnSmBiosInterfacesAdded end
    if origs.client_OnSmBiosPropertiesChanged then client.OnSmBiosPropertiesChanged = origs.client_OnSmBiosPropertiesChanged end
    if origs.client_GetSmBiosObjects then client.GetSmBiosObjects = origs.client_GetSmBiosObjects end
    if origs.client_ForeachSmBiosObjects then client.ForeachSmBiosObjects = origs.client_ForeachSmBiosObjects end
    if origs.client_OnComponentInterfacesAdded then client.OnComponentInterfacesAdded = origs.client_OnComponentInterfacesAdded end
    if origs.client_OnComponentPropertiesChanged then client.OnComponentPropertiesChanged = origs.client_OnComponentPropertiesChanged end
    if origs.client_ForeachComponentObjects then client.ForeachComponentObjects = origs.client_ForeachComponentObjects end
    if origs.fructl_get_power_status then fructl.get_power_status = origs.fructl_get_power_status end
    if origs.log_collector_log_dump_reset_bmc_sig then log_collector.log_dump_reset_bmc_sig = origs.log_collector_log_dump_reset_bmc_sig end
    if origs.log_collector_log_dump_reset_smbios_sig then log_collector.log_dump_reset_smbios_sig = origs.log_collector_log_dump_reset_smbios_sig end
end

-- 1) preload 无或 PortCount 为空：handle_port_count_mismatch 直接 return，不报 device not found
function TestCardMgmt:test_handle_port_count_mismatch_no_preload()
    local origs = {
        preload_find = c_network_adapter_preload.collection.find,
        get_instance = c_object_manage.get_instance,
        get_device_obj = comm_fun.get_device_obj_by_path_interface,
        get_object_name = comm_fun.get_object_name_by_device_path,
        get_object_identifier = comm_fun.get_object_identifier_by_device_path,
        set_interface_add_signal = comm_fun.set_interface_add_signal,
        ctx_get_context = ctx.get_context_or_default,
        mdb_register = mdb.register_interface,
        mdb_get_object = mdb.get_object,
        create_mdb_object = c_network_adapter.create_mdb_object,
        factory_get_instance = c_factory.get_instance,
        card_init_init = card_init.init,
        log_error = log.error,
        log_notice = log.notice,
    }
    local bus = {}
    local device_path = '/test/card/path'
    local setup_origs = setup_init_obj_stubs_for_network_port_count(bus, 4)
    for k, v in pairs(setup_origs) do origs[k] = v end
    c_network_adapter_preload.collection.find = function(_, q)
        return nil
    end
    c_object_manage.get_instance = function() return { bus = bus } end
    comm_fun.get_device_obj_by_path_interface = function() return {} end
    c_network_adapter.collection.find = function(_, q)
        return {
            NodeId = 'NodeId_Test',
            children = {},
            device_path = device_path,
            connect_signal = function() end,
            next_tick = function(_, fn) if fn then fn() end end,
        }
    end
    local orig_collection_find = c_network_adapter.collection.find

    local mgr = card_mgmt
    mgr.bus = bus
    mgr.objects = {}
    mgr.sig_slot = {}
    mgr:init_obj(device_path)

    lu.assertNotNil(mgr.objects[device_path], 'card orm object should be created')
    restore_handle_port_count_mismatch_stubs(origs)
    c_network_adapter.collection.find = orig_collection_find
end

-- 2) preload 有 PortCount，但 OEM 设备对象未找到：打 log error 并 return
function TestCardMgmt:test_handle_port_count_mismatch_oem_device_not_found()
    local log_errors = {}
    local origs = {
        preload_find = c_network_adapter_preload.collection.find,
        get_instance = c_object_manage.get_instance,
        get_device_obj = comm_fun.get_device_obj_by_path_interface,
        get_object_name = comm_fun.get_object_name_by_device_path,
        get_object_identifier = comm_fun.get_object_identifier_by_device_path,
        set_interface_add_signal = comm_fun.set_interface_add_signal,
        ctx_get_context = ctx.get_context_or_default,
        mdb_register = mdb.register_interface,
        mdb_get_object = mdb.get_object,
        create_mdb_object = c_network_adapter.create_mdb_object,
        factory_get_instance = c_factory.get_instance,
        card_init_init = card_init.init,
        log_error = log.error,
        log_notice = log.notice,
    }
    local bus = {}
    local device_path = '/test/card/path'
    local setup_origs = setup_init_obj_stubs_for_network_port_count(bus, 2)
    for k, v in pairs(setup_origs) do origs[k] = v end
    c_network_adapter_preload.collection.find = function(_, q)
        return { NodeId = 'NodeId_Test', PortCount = 4 }
    end
    c_object_manage.get_instance = function() return { bus = bus } end
    comm_fun.get_device_obj_by_path_interface = function(bus_arg, path, iface)
        if iface == comm_defs.NETWORK_ADAPTER_OEM_INTERFACE then
            return nil
        end
        return {}
    end
    c_network_adapter.collection.find = function(_, q)
        return {
            NodeId = 'NodeId_Test',
            children = {},
            device_path = device_path,
            connect_signal = function() end,
            next_tick = function(_, fn) if fn then fn() end end,
        }
    end
    local orig_collection_find = c_network_adapter.collection.find
    log.error = function(_, fmt, ...)
        table.insert(log_errors, string.format(fmt, ...))
    end

    local mgr = card_mgmt
    mgr.bus = bus
    mgr.objects = {}
    mgr.sig_slot = {}
    mgr:init_obj(device_path)

    local found = false
    for _, msg in ipairs(log_errors) do
        if string.find(msg, 'set preload port count failed') and string.find(msg, 'network adapter device object not found') then
            found = true
            break
        end
    end
    lu.assertTrue(found, 'should log error when OEM device object not found')

    restore_handle_port_count_mismatch_stubs(origs)
    c_network_adapter.collection.find = orig_collection_find
end

-- 3) 当前端口数 == preload PortCount：设置 IsPortCountMatched = 1，不调用 SetPreloadPortCount
function TestCardMgmt:test_handle_port_count_mismatch_matched()
    local set_preload_called = false
    local oem_device = { IsPortCountMatched = -1 }
    local origs = {
        preload_find = c_network_adapter_preload.collection.find,
        get_instance = c_object_manage.get_instance,
        get_device_obj = comm_fun.get_device_obj_by_path_interface,
        get_object_name = comm_fun.get_object_name_by_device_path,
        get_object_identifier = comm_fun.get_object_identifier_by_device_path,
        set_interface_add_signal = comm_fun.set_interface_add_signal,
        ctx_get_context = ctx.get_context_or_default,
        mdb_register = mdb.register_interface,
        mdb_get_object = mdb.get_object,
        create_mdb_object = c_network_adapter.create_mdb_object,
        factory_get_instance = c_factory.get_instance,
        card_init_init = card_init.init,
        log_error = log.error,
        log_notice = log.notice,
    }
    local bus = {}
    local device_path = '/test/card/path'
    local setup_origs = setup_init_obj_stubs_for_network_port_count(bus, 4)
    for k, v in pairs(setup_origs) do origs[k] = v end
    c_network_adapter_preload.collection.find = function(_, q)
        return { NodeId = 'NodeId_Test', PortCount = 4 }
    end
    c_object_manage.get_instance = function() return { bus = bus } end
    comm_fun.get_device_obj_by_path_interface = function(bus_arg, path, iface)
        if iface == comm_defs.NETWORK_ADAPTER_OEM_INTERFACE then
            return oem_device
        end
        return {}
    end
    c_network_adapter.collection.find = function(_, q)
        return {
            NodeId = 'NodeId_Test',
            children = {},
            device_path = device_path,
            connect_signal = function() end,
            next_tick = function(_, fn) if fn then fn() end end,
        }
    end
    local orig_collection_find = c_network_adapter.collection.find

    local mgr = card_mgmt
    mgr.bus = bus
    mgr.objects = {}
    mgr.sig_slot = {}
    mgr:init_obj(device_path)

    lu.assertEquals(oem_device.IsPortCountMatched, 1)
    lu.assertFalse(set_preload_called)

    restore_handle_port_count_mismatch_stubs(origs)
    c_network_adapter.collection.find = orig_collection_find
end

-- 4) 端口数不一致，SetPreloadPortCount 成功：打 notice，IsPortCountMatched = 0
function TestCardMgmt:test_handle_port_count_mismatch_mismatch_set_success()
    local notice_logs = {}
    local oem_device = {
        IsPortCountMatched = -1,
        call_method = function(self, method, signature, port_count)
            if method == 'SetPreloadPortCount' then
                return true
            end
            return false
        end,
    }
    local origs = {
        preload_find = c_network_adapter_preload.collection.find,
        get_instance = c_object_manage.get_instance,
        get_device_obj = comm_fun.get_device_obj_by_path_interface,
        get_object_name = comm_fun.get_object_name_by_device_path,
        get_object_identifier = comm_fun.get_object_identifier_by_device_path,
        set_interface_add_signal = comm_fun.set_interface_add_signal,
        ctx_get_context = ctx.get_context_or_default,
        mdb_register = mdb.register_interface,
        mdb_get_object = mdb.get_object,
        create_mdb_object = c_network_adapter.create_mdb_object,
        factory_get_instance = c_factory.get_instance,
        card_init_init = card_init.init,
        log_error = log.error,
        log_notice = log.notice,
    }
    local bus = {}
    local device_path = '/test/card/path'
    local setup_origs = setup_init_obj_stubs_for_network_port_count(bus, 2)
    for k, v in pairs(setup_origs) do origs[k] = v end
    c_network_adapter_preload.collection.find = function(_, q)
        return { NodeId = 'NodeId_Test', PortCount = 4 }
    end
    c_object_manage.get_instance = function() return { bus = bus } end
    comm_fun.get_device_obj_by_path_interface = function(bus_arg, path, iface)
        if iface == comm_defs.NETWORK_ADAPTER_OEM_INTERFACE then
            return oem_device
        end
        return {}
    end
    c_network_adapter.collection.find = function(_, q)
        return {
            NodeId = 'NodeId_Test',
            children = {},
            device_path = device_path,
            connect_signal = function() end,
            next_tick = function(_, fn) if fn then fn() end end,
        }
    end
    local orig_collection_find = c_network_adapter.collection.find
    log.notice = function(_, fmt, ...)
        table.insert(notice_logs, string.format(fmt, ...))
    end

    local mgr = card_mgmt
    mgr.bus = bus
    mgr.objects = {}
    mgr.sig_slot = {}
    mgr:init_obj(device_path)

    lu.assertEquals(oem_device.IsPortCountMatched, 0)
    local found_success = false
    for _, msg in ipairs(notice_logs) do
        if string.find(msg, 'set preload port count successfully') then
            found_success = true
            break
        end
    end
    lu.assertTrue(found_success, 'should log notice when SetPreloadPortCount succeeds')

    restore_handle_port_count_mismatch_stubs(origs)
    c_network_adapter.collection.find = orig_collection_find
end

-- 5) 端口数不一致，SetPreloadPortCount 失败：打 error，IsPortCountMatched = 0
function TestCardMgmt:test_handle_port_count_mismatch_mismatch_set_failed()
    local error_logs = {}
    local oem_device = {
        IsPortCountMatched = -1,
        call_method = function(self, method, signature, port_count)
            if method == 'SetPreloadPortCount' then
                return false
            end
            return false
        end,
    }
    local origs = {
        preload_find = c_network_adapter_preload.collection.find,
        get_instance = c_object_manage.get_instance,
        get_device_obj = comm_fun.get_device_obj_by_path_interface,
        get_object_name = comm_fun.get_object_name_by_device_path,
        get_object_identifier = comm_fun.get_object_identifier_by_device_path,
        set_interface_add_signal = comm_fun.set_interface_add_signal,
        ctx_get_context = ctx.get_context_or_default,
        mdb_register = mdb.register_interface,
        mdb_get_object = mdb.get_object,
        create_mdb_object = c_network_adapter.create_mdb_object,
        factory_get_instance = c_factory.get_instance,
        card_init_init = card_init.init,
        log_error = log.error,
        log_notice = log.notice,
    }
    local bus = {}
    local device_path = '/test/card/path'
    local setup_origs = setup_init_obj_stubs_for_network_port_count(bus, 2)
    for k, v in pairs(setup_origs) do origs[k] = v end
    c_network_adapter_preload.collection.find = function(_, q)
        return { NodeId = 'NodeId_Test', PortCount = 4 }
    end
    c_object_manage.get_instance = function() return { bus = bus } end
    comm_fun.get_device_obj_by_path_interface = function(bus_arg, path, iface)
        if iface == comm_defs.NETWORK_ADAPTER_OEM_INTERFACE then
            return oem_device
        end
        return {}
    end
    c_network_adapter.collection.find = function(_, q)
        return {
            NodeId = 'NodeId_Test',
            children = {},
            device_path = device_path,
            connect_signal = function() end,
            next_tick = function(_, fn) if fn then fn() end end,
        }
    end
    local orig_collection_find = c_network_adapter.collection.find
    log.error = function(_, fmt, ...)
        table.insert(error_logs, string.format(fmt, ...))
    end

    local mgr = card_mgmt
    mgr.bus = bus
    mgr.objects = {}
    mgr.sig_slot = {}
    mgr:init_obj(device_path)

    lu.assertEquals(oem_device.IsPortCountMatched, 0)
    local found_err = false
    for _, msg in ipairs(error_logs) do
        if string.find(msg, 'set preload port count failed') then
            found_err = true
            break
        end
    end
    lu.assertTrue(found_err, 'should log error when SetPreloadPortCount fails')

    restore_handle_port_count_mismatch_stubs(origs)
    c_network_adapter.collection.find = orig_collection_find
end

-- 覆盖 card_mgmt:update_firmware_version（card_mgmt.lua 581-600）
function TestCardMgmt:test_update_firmware_version_skips_when_not_created_by_device_object()
    local orig_get = comm_fun.get_device_obj_by_path_interface
    local called = false
    comm_fun.get_device_obj_by_path_interface = function()
        called = true
        return {}
    end
    local mgr = card_mgmt
    mgr.bus = {}
    mgr:update_firmware_version({
        CreatedByDeviceObject = false,
        NodeId = 'NA_SKIP',
        device_path = '/any',
    }, '1.0.0')
    lu.assertFalse(called)
    comm_fun.get_device_obj_by_path_interface = orig_get
end

function TestCardMgmt:test_update_firmware_version_fails_when_device_path_empty()
    local orig_get = comm_fun.get_device_obj_by_path_interface
    local errors = {}
    local orig_notice, orig_error = log.notice, log.error
    log.notice = function() end
    log.error = function(_, fmt, ...)
        table.insert(errors, string.format(fmt, ...))
    end
    comm_fun.get_device_obj_by_path_interface = function()
        error('should not get device when path empty')
    end
    local mgr = card_mgmt
    mgr.bus = {}
    mgr:update_firmware_version({
        CreatedByDeviceObject = true,
        NodeId = 'NA_EMPTY',
        device_path = '',
    }, '1.0.0')
    local hit = false
    for _, msg in ipairs(errors) do
        if msg:find('port_device_path is nil or empty') then
            hit = true
            break
        end
    end
    lu.assertTrue(hit)
    log.notice = orig_notice
    log.error = orig_error
    comm_fun.get_device_obj_by_path_interface = orig_get
end

function TestCardMgmt:test_update_firmware_version_fails_when_device_path_nil()
    local orig_get = comm_fun.get_device_obj_by_path_interface
    local errors = {}
    local orig_notice, orig_error = log.notice, log.error
    log.notice = function() end
    log.error = function(_, fmt, ...)
        table.insert(errors, string.format(fmt, ...))
    end
    comm_fun.get_device_obj_by_path_interface = function()
        error('should not get device when path nil')
    end
    local mgr = card_mgmt
    mgr.bus = {}
    mgr:update_firmware_version({
        CreatedByDeviceObject = true,
        NodeId = 'NA_NIL_PATH',
        device_path = nil,
    }, '1.0.0')
    lu.assertEquals(#errors, 1)
    lu.assertNotNil(string.find(errors[1], 'port_device_path is nil or empty', 1, true))
    log.notice = orig_notice
    log.error = orig_error
    comm_fun.get_device_obj_by_path_interface = orig_get
end

function TestCardMgmt:test_update_firmware_version_fails_when_card_device_obj_nil()
    local orig_get = comm_fun.get_device_obj_by_path_interface
    local errors = {}
    local orig_notice, orig_error = log.notice, log.error
    log.notice = function() end
    log.error = function(_, fmt, ...)
        table.insert(errors, string.format(fmt, ...))
    end
    local bus = {}
    comm_fun.get_device_obj_by_path_interface = function(b, path, iface)
        lu.assertIs(b, bus)
        lu.assertEquals(path, '/ut/card0')
        lu.assertEquals(iface, comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE)
        return nil
    end
    local mgr = card_mgmt
    mgr.bus = bus
    mgr:update_firmware_version({
        CreatedByDeviceObject = true,
        NodeId = 'NA_NIL_DEV',
        device_path = '/ut/card0',
    }, '2.0.0')
    local hit = false
    for _, msg in ipairs(errors) do
        if msg:find('card_device_obj is nil') and msg:find('/ut/card0') then
            hit = true
            break
        end
    end
    lu.assertTrue(hit)
    log.notice = orig_notice
    log.error = orig_error
    comm_fun.get_device_obj_by_path_interface = orig_get
end

function TestCardMgmt:test_update_firmware_version_success_sets_property()
    local orig_get = comm_fun.get_device_obj_by_path_interface
    local bus = {}
    local dbus_card = { FirmwareVersion = 'old' }
    comm_fun.get_device_obj_by_path_interface = function(b, path, iface)
        lu.assertIs(b, bus)
        lu.assertEquals(path, '/ut/card_ok')
        lu.assertEquals(iface, comm_defs.NETWORK_ADAPTER_DEVICE_INTERFACE)
        return dbus_card
    end
    local mgr = card_mgmt
    mgr.bus = bus
    mgr:update_firmware_version({
        CreatedByDeviceObject = true,
        NodeId = 'NA_OK',
        device_path = '/ut/card_ok',
    }, 'FW_NEW')
    lu.assertEquals(dbus_card.FirmwareVersion, 'FW_NEW')
    comm_fun.get_device_obj_by_path_interface = orig_get
end

return TestCardMgmt
