-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.

local lu = require 'luaunit'
local network_adapter_app = require 'network_adapter_app'
local c_network_adapter = require 'device.class.network_adapter'
local c_object_manage = require 'mc.orm.object_manage'
local c_tasks = require 'mc.orm.tasks'
local c_network_port = require 'device.class.network_port'
local c_network_adapter_db = require 'network_adapter.db'
local hook_tasks = require 'test_common.hook_tasks'
local test_utils = require 'test_utils'
local create_mds_object = test_utils.create_mds_object
local vos = require 'utils.vos'
local utils = require 'mc.utils'
local c_optical_module = require 'device.class.optical_module'
local hi1822 = require 'hardware_config.Hi182X'
local bf2 = require 'hardware_config.BF2'
local cx4 = require 'hardware_config.CX4'
local cx5 = require 'hardware_config.CX5'
local cx7 = require 'hardware_config.CX7'
local cx6_dx = require 'hardware_config.CX6-DX'
local bf3 = require 'hardware_config.BF3'
local bs = require 'mc.bitstring'
local c_network_bonding = require 'device.class.network_bonding'
local c_handler_eth = require 'bma.handles.handler_eth'
local c_handler_fc = require 'bma.handles.handler_fc'
local pmu_cmd = require 'imu'
local skynet = require 'skynet'
local mctp_lib = require 'mctp_lib'

TEST_network_adapter = {}

function TEST_network_adapter:test_RequireConfig()
    local table_1822 = hi1822.smbus().properties
    for _, func in pairs(table_1822) do
        pcall(func.response)
    end
    local table_1822_ncsi = hi1822.mctp().properties
    for _, func in pairs(table_1822_ncsi) do
        pcall(func.response)
    end
    local table_cx4 = cx4.mctp().properties
    for _, func in pairs(table_cx4) do
        pcall(func.response)
    end
    local table_cx5 = cx5.mctp().properties
    for _, func in pairs(table_cx5) do
        pcall(func.response)
    end
    local table_cx6_dx = cx6_dx.mctp().properties
    for _, func in pairs(table_cx6_dx) do
        pcall(func.response)
    end
    local table_cx7 = cx7.mctp().properties
    for _, func in pairs(table_cx7) do
        pcall(func.response)
    end
    local table_bf3 = bf3.mctp().properties
    for _, func in pairs(table_bf3) do
        pcall(func.response)
    end
end

function TEST_network_adapter:setUp()
    self.database = c_network_adapter_db(':memory:')

    hook_tasks.hook()
    self.object_manage = c_object_manage.new(self.database)
    self.object_manage.app = self

    self.position = '00010102'
    self.network_adapter_obj = test_utils.add_network_adapter(self.object_manage, 'NetworkAdapter_1', {
        BoardID = 0x123,
        DeviceLocator = 'some locator',
        Name = "",
        Position = self.position
    })
    self.object_manage.mc:before_add_object(c_network_adapter.__class_name, self.network_adapter_obj)
    self.object_manage.mc:add_object(c_network_adapter.__class_name, self.network_adapter_obj,
        self.position)
    self.object_manage.mc:prepare_ok()
    self:flush()
end

function TEST_network_adapter:CreateVLANs()
end

function TEST_network_adapter:tearDown()
    c_object_manage.destroy()
    self.database.db:close()
    hook_tasks.unhook()
end

function TEST_network_adapter:flush()
    c_tasks.get_instance():run_all_task()
    self.database.db:flush()
end

function TEST_network_adapter:test_can_construct_network_adapter()
    local adapter = c_network_adapter.collection:find({Position = self.position})

    lu.assertEquals(adapter.Position, self.position)
    lu.assertEquals(adapter.ID, self.position .. 'somelocator')
    lu.assertEquals(adapter.BoardIDHex, '0x0123')
end

function TEST_network_adapter:test_can_deconstruct_network_adapter()
    local adapter = c_network_adapter.collection:find({Position = self.position})

    local r = {ports_deconstruct_called = 0, scheduler_deconstruct_called = 0}
    c_network_port.stop = function()
        r.ports_deconstruct_called = 1
    end

    -- 自发现添加 port 对象
    local mds_network_port = create_mds_object('NetworkPort_1', {PortID = 1, NetDevFuncType = 1},
        self.network_adapter_obj,
        '/bmc/kepler/Systems/1/NetworkAdapters/NetworkAdapter_1_0001010101')
    self.object_manage.mc:before_add_object(c_network_port.__class_name, mds_network_port)
    self.object_manage.mc:add_object(c_network_port.__class_name, mds_network_port, self.position)

    local scheduler_expect_call<const> = 10
    for i = 1, scheduler_expect_call do
        adapter.ncsi_schedulers[i] = {
            deconstruct = function()
                r.scheduler_deconstruct_called = r.scheduler_deconstruct_called + 1
            end
        }
    end
    self.object_manage.mc:add_object_complete(self.position)

    -- 自发现删除对象
    self.object_manage.mc:del_object(c_network_port.__class_name, mds_network_port, self.position)
    self.object_manage.mc:del_object(c_network_adapter.__class_name, self.network_adapter_obj,
        self.position)

    lu.assertEquals(r.ports_deconstruct_called, 1)
    lu.assertEquals(r.scheduler_deconstruct_called, scheduler_expect_call)
end

function TEST_network_adapter:test_network_adapter_collect_dump_info()
    self.network_adapter_obj.Name = 'SP580'
    self.network_portobj = test_utils.add_network_port(self.object_manage, 'NetworkPort_1',
        {PortID = 0, PermanentMACAddress = '04:8C:16:59:C9:3E', MACAddress = '04:8C:16:59:C9:3E',
            LinkStatus = 'LinkDown'},
        self.position, self.network_adapter_obj)
    self.optical_module_obj = test_utils.add_optical_module(self.object_manage, 'OpticalModule_1',
        {FaultState = 0, Presence = 0, Manufacturer = 'Huawei', SerialNumber = 'INHAX4480013'},
        self.position, self.network_portobj)
    test_utils.add_object_complete(self.object_manage, self.position)
    local bma = {handles = {[3] = {objects = {[self.network_portobj] =
        '/redfish/v1/Sms/1/Systems/1/EthernetInterfaces/0000:bc:00.0_0000:bd:00.0'}}}}
    c_network_adapter.collect_dump_info('/var/log', bma)
    lu.assertEquals(vos.get_file_accessible('/var/log/net_card_info'), true)
    self.object_manage.mc:del_object(c_network_adapter.__class_name, self.network_adapter_obj,
        self.position)
    self.object_manage.mc:del_object(c_network_port.__class_name, self.network_portobj, self.position)
    self.object_manage.mc:del_object(c_optical_module.__class_name, self.optical_module_obj, self.position)
    utils.remove_file('/var/log/net_card_info')

    c_network_adapter.collect_dump_info('/var/log', bma)
    lu.assertEquals(vos.get_file_accessible('/var/log/net_card_info'), true)
end

function TEST_network_adapter:test_network_adapter_collect_static_optical_info()
    local col_tab = c_optical_module.collection 
    local opt_info = {
        PortID = 0,
        NpuID = '123',
        Manufacturer = "test",
        SerialNumber = "123",
        TransceiverType = '1',
        Presence = 1
    }
    c_optical_module.collection  = {
        fetch_by_position = function (...)
            return {
                test = {
                    get_parent = function (...)
                        return opt_info
                    end
                }
            }
        end       
    }
    local net = {
        get_position = function (...)
            return 'test'
        end
    }
    local ret = c_network_adapter.collect_optical_static_info(net)
    lu.assertEquals(#ret, 144)
    opt_info.NpuID = nil
    ret = c_network_adapter.collect_optical_static_info(net)
    lu.assertEquals(#ret, 0)
    opt_info.NpuID = '123'
    opt_info.PortID = 1
    ret = c_network_adapter.collect_optical_static_info(net)
    lu.assertEquals(#ret, 93)
    c_optical_module.collection = col_tab
end

-- 十六进制字符转ascii字符
local function hex_to_ascii(mac)
    local hex = string.gsub(mac, ":", "")
    -- 非法mac地址置零
    if string.find(hex, "[^%x]") then
        return "\0\0\0\0\0\0"
    end
    local str = {}
    local byte
    -- 十六进制字符转换
    for i = 1, #hex, 2 do
        byte = string.sub(hex, i, i + 1)
        table.insert(str, string.char(tonumber(byte, 16)))
    end
    return table.concat(str)
end

local function get_port_mac_hex(port)
    local str = "\0\0\0\0\0\0"
    if not port then
        return str
    end

    local mac = port.PermanentMACAddress
    -- 非法mac地址置零
    if mac and #mac == 17 then
        str = hex_to_ascii(mac)
    end
    return str
end

local function get_uuid_pack_str(ports)
    table.sort(ports, function(a, b)
        return a.PortID < b.PortID
    end)
    local mac1 = get_port_mac_hex(ports[1])
    local mac2 = get_port_mac_hex(ports[2])
    local mac3 = get_port_mac_hex(ports[3])
    local mac4 = get_port_mac_hex(ports[4])
    -- 网口个数小于等于2个时，取两个网口的mac共96位，剩余32位用0补齐
    -- 网口个数大于2个，取第一个网口的mac（48位），后三个网口的低24位共120位，
    -- 剩余8位用0补齐
    if #ports <= 2 then
        return string.pack("<c6c6c4", mac1, mac2, string.rep('\0', 4))
    end
    return string.pack("<c6c3c3c3c1", mac1, string.sub(mac2, 4, 6),
                string.sub(mac3, 4, 6), string.sub(mac4, 4, 6), '\0')
end

local function regenerate_uuid_str(pack_string)
    local partten_mac = bs.new([[<<
        custom_a:48/big,
        custom_b:4,
        custom_c:4,
        custom_d:4,
        custom_e:4,
        custom_f:56/big,
        custom_g:8/big>>]])
    local uuid_part = partten_mac:unpack(pack_string)
    local uuid_param = {
        custom_a = uuid_part.custom_a,
        custom_b = uuid_part.custom_c,
        ver = 8,
        custom_c = uuid_part.custom_e,
        custom_d = uuid_part.custom_b,
        custom_e = uuid_part.custom_d,
        var = 8,
        custom_f = uuid_part.custom_f
    }
    local partten_uuid = bs.new([[<<
        custom_a:48/big,
        custom_b:4,
        ver:4,
        custom_c:4,
        custom_d:4,
        custom_e:4,
        var:4,
        custom_f:56/big>>]])
    return partten_uuid:pack(uuid_param)
end

function TEST_network_adapter:test_network_adapter_uuid()
    local network_port_objs = {
        {
            PermanentMACAddress = "00:15:5d:34:80:59",
            PortID = 0
        },
        {
            PermanentMACAddress = "00:15:5d:34:80:5A",
            PortID = 1
        },
        {
            PermanentMACAddress = "00:15:5d:34:80:5B",
            PortID = 2
        },
        {
            PermanentMACAddress = "00:15:5d:34:80:5C",
            PortID = 3
        }
    }

    local uuid8_1 = regenerate_uuid_str(get_uuid_pack_str({network_port_objs[1]}))
    local uuid8_2 = regenerate_uuid_str(get_uuid_pack_str({network_port_objs[1], network_port_objs[2]}))
    local uuid8_3 = regenerate_uuid_str(
        get_uuid_pack_str({network_port_objs[1], network_port_objs[2], network_port_objs[3]}))
    local uuid8_4 = regenerate_uuid_str(get_uuid_pack_str(network_port_objs))
    local uuid8_4_2 = regenerate_uuid_str(get_uuid_pack_str(network_port_objs))
    lu.assertEquals(uuid8_4, uuid8_4_2)
    lu.assertEquals(uuid8_1, '\x00\x15\x5D\x34\x80\x59\x80\x00\x80\x00\x00\x00\x00\x00\x00\x00')
    lu.assertEquals(uuid8_2, '\x00\x15\x5D\x34\x80\x59\x80\x01\x85\x5d\x34\x80\x5a\x00\x00\x00')
    lu.assertEquals(uuid8_3, '\x00\x15\x5D\x34\x80\x59\x83\x48\x80\x5a\x34\x80\x5b\x00\x00\x00')
    lu.assertEquals(uuid8_4, '\x00\x15\x5D\x34\x80\x59\x83\x48\x80\x5a\x34\x80\x5b\x34\x80\x5c')
end

function TEST_network_adapter:test_network_bonding_update_ports()
    local value = {
        Id = 1,
        Ports = 1
    }
    local ok, _ = pcall(function()
        c_network_bonding.update_ports(value)
    end)
    lu.assertEquals(ok, true)
end

function TEST_network_adapter:test_update_network_port_linkstatus()
    local port = {}
    local data = {}
    local oem_huawei = {}

    port.update_ipv6_default_gateway = function()
    end
    port.set_link_status_numeric = function()
    end

    data.LinkStatus = ''
    local ok, _ = pcall(function()
        c_handler_eth:update_network_port(port, data, oem_huawei)
    end)
    lu.assertEquals(ok, true)
    lu.assertEquals(port.OSLinkStatus, 'N/A')

    data.LinkStatus = 'LinkUp'
    local ok, _ = pcall(function()
        c_handler_eth:update_network_port(port, data, oem_huawei)
    end)
    lu.assertEquals(ok, true)
    lu.assertEquals(port.OSLinkStatus, 'LinkUp')

    data.LinkStatus = 'LinkUp'
    port.NetDevFuncType = 32
    local ok, _ = pcall(function()
        c_handler_eth:update_network_port(port, data, oem_huawei)
    end)
    lu.assertEquals(ok, true)
    lu.assertEquals(port.OSLinkStatus, 'LinkUp')

    data.PhysicalPort = {}
    data.PhysicalPort.LinkStatus = 'Online'
    local ok, _ = pcall(function()
        c_handler_fc:update_fc_network_port(port, data)
    end)
    lu.assertEquals(ok, true)
    lu.assertEquals(port.OSLinkStatus, 'LinkUp')

    data.PhysicalPort.LinkStatus = 'Offline'
    local ok, _ = pcall(function()
        c_handler_fc:update_fc_network_port(port, data)
    end)
    lu.assertEquals(ok, true)
    lu.assertEquals(port.OSLinkStatus, 'LinkDown')
end

function TEST_network_adapter:test_mctp()
    c_network_adapter.ncsi_schedulers = {}
    local origin_ncsi_schedulers = c_network_adapter.ncsi_schedulers
    c_network_adapter.ncsi_config_obj = {
        DisableHardwareArbitration = function()
            return {
                value = function() return true end
            }
        end,
        ChipTemp = function()
            return {
                on_data_change = { on = function(data) end },
                start = function () end,
                on_error = { on = function(data) end }
            }
        end,
        LinkAbility = function()
            return {
                value = function() return {} end
            }
        end,
        LinkInfo = function()
            return {
                value = function() return {} end
            }
        end,
        FaultStatCode = function()
            return {
                on_data_change = { on = function(_, cb) cb({health_status=0}) end },
                on_error = { on = function(data) end },
                start = function () end
            }
        end,
        VendorID = function()
            return {
                on_data_change = { on = function(data) end },
                start = function () end
            }
        end,
        GetOSStatus = function()
            return {
                on_data_change = { on = function(data) end },
                start = function () end
            }
        end,
    }
    c_network_adapter:disable_hardware_arbittration()
    cx5.mctp().properties.DisableHardwareArbitration.response('\x00\x00\x00\x00')
    local res = hi1822.mctp().properties.OpticalModuleInfo.response(
        string.pack('<c85','aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' .. '\x01' ..
            'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'))
    lu.assertEquals(res.MediumType, 'Optical')
    bf2.mctp().properties.GetOSStatus.response('\x00\x00\x00\x00\x05')
    c_network_adapter:update_chip_temp_by_ncsi()
    c_network_adapter:update_link_ability_by_ncsi()
    c_network_adapter:update_link_status_by_ncsi()
    c_network_adapter:update_error_code_by_ncsi()
    c_network_adapter:update_ncsi_firmware({})
    c_network_adapter:fetch_dpu_os_status_by_ncsi()
    c_network_adapter.ncsi_schedulers = origin_ncsi_schedulers
end

function TEST_network_adapter:test_get_max_npu_cdr_temp_from_imu()
    c_network_adapter:get_max_npu_cdr_temp_from_imu()
end

function TEST_network_adapter:test_update_max_npu_cdr_temp_from_imu()
    local network_port_objs = {
        { PortID = 0 }, { PortID = 1 }, { PortID = 2 }, { PortID = 3 }
    }
    for _, port in ipairs(network_port_objs) do
        port.get_npu_cdr_temp_from_imu = function()
            return 40
        end
    end
    c_network_adapter.TemperatureStatus = 0
    c_network_adapter:update_max_npu_cdr_temp_from_imu(network_port_objs)
    lu.assertEquals(c_network_adapter.TemperatureCelsius, 40)

    network_port_objs = { { npu_port_cdr_info_abnormal = true } }
    for _, port in ipairs(network_port_objs) do
        port.get_npu_cdr_temp_from_imu = function()
            return 40
        end
    end
    c_network_adapter.TemperatureStatus = 0
    c_network_adapter:update_max_npu_cdr_temp_from_imu(network_port_objs)
    lu.assertEquals(c_network_adapter.TemperatureStatus, 3)
end

c_network_adapter.cdr_overtemp_table = {}
function TEST_network_adapter:test_update_max_npu_cdr_temp_from_imu_0()
    local network_port_objs = {
        { PortID = 0 , NpuID = 0}
    }
    for _, port in ipairs(network_port_objs) do
        port.get_npu_cdr_temp_from_imu = function()
            return 90, ''
        end
    end
    c_network_adapter:update_max_npu_cdr_temp_from_imu(network_port_objs)
    lu.assertEquals(c_network_adapter.cdr_overtemp_table.max_temp, 0)
end

function TEST_network_adapter:test_update_max_npu_cdr_temp_from_imu_1()
    local network_port_objs = {
        { PortID = 0 , NpuID = 0}
    }
    for _, port in ipairs(network_port_objs) do
        port.get_npu_cdr_temp_from_imu = function()
            return 101, ''
        end
    end
    c_network_adapter:update_max_npu_cdr_temp_from_imu(network_port_objs)
    lu.assertEquals(c_network_adapter.cdr_overtemp_table.max_temp, 101)
end

function TEST_network_adapter:test_update_max_npu_cdr_temp_from_imu_2()
    local network_port_objs = {
        { PortID = 0 , NpuID = 0}
    }
    for _, port in ipairs(network_port_objs) do
        port.get_npu_cdr_temp_from_imu = function()
            return 110, ''
        end
    end
    c_network_adapter:update_max_npu_cdr_temp_from_imu(network_port_objs)
    lu.assertEquals(c_network_adapter.cdr_overtemp_table.max_temp, 110)
end

function TEST_network_adapter:test_update_max_npu_cdr_temp_from_imu_3()
    local network_port_objs = {
        { PortID = 0 , NpuID = 0}
    }
    for _, port in ipairs(network_port_objs) do
        port.get_npu_cdr_temp_from_imu = function()
            return 105, ''
        end
    end
    c_network_adapter:update_max_npu_cdr_temp_from_imu(network_port_objs)
    lu.assertEquals(c_network_adapter.cdr_overtemp_table.max_temp, 105)
end

function TEST_network_adapter:test_update_max_npu_cdr_temp_from_imu_4()
    local network_port_objs = {
        { PortID = 0 , NpuID = 0}
    }
    for _, port in ipairs(network_port_objs) do
        port.get_npu_cdr_temp_from_imu = function()
            return 90, ''
        end
    end
    c_network_adapter:update_max_npu_cdr_temp_from_imu(network_port_objs)
    lu.assertEquals(c_network_adapter.cdr_overtemp_table.max_temp, 0)
end

function TEST_network_adapter:test_register_npu_listen_callback()
    local client = require 'network_adapter.client'
    local func = client.OnFruCtrlPropertiesChanged
    client.values = {
        SysResetDetected = {
            value = function()
                return 1
            end
        },
        PowerState = {
            value = function()
                return "OFF"
            end
        }
    }
    client.OnFruCtrlPropertiesChanged = function(self, cb)
        cb(self.values, 1, 2)
    end
    local collection = c_network_port.collection
    c_network_port.collection = {
        obj = {
            get_parent = function()
                return {
                    Model = "NPU"
                }
            end
        }
    }
    c_network_port.collection.fold = function(self, cb)
        cb(1, self.obj)
    end
    c_network_adapter.register_npu_listen_callback()
    client.OnFruCtrlPropertiesChanged = func
    c_network_port.collection = collection
end

function TEST_network_adapter:test_firmware_version()
    local properties = hi1822.mctp().properties
    local vendor = properties.VendorID
    local response =vendor.response
    local tmp = bs.new
    bs.new = function()
        return {unpack = function(data, flag)
            return {
                ncsi_version_major=8,
                ncsi_version_minor=8, 
                ncsi_version_update=8, 
                ncsi_version_alpha1=8, 
                ncsi_version_alpha2=8,
                firmware_version_0=8,
                firmware_version_1=8,
                firmware_version_2=8,
                firmware_version_3=8,
                pci_vid=16,
                pci_did=16,
                pci_svid=16,
                pci_ssid=16
            }
        end, pack = function()
            return "test"
        end}
    end
    local ok, _ = pcall(function()
        return response(1)
    end)
    lu.assertEquals(ok, true)
    bs.new = tmp
end

function TEST_network_adapter:test_update_ncsi_properties()
    local ports = {
        ['BF3'] = {
            set_ncsi_config_obj = function ()
                return nil
            end,
            set_package_id = function(port, package_id)
                port.package_id = package_id
            end,
            set_smbus_schedulers = function ()
                return nil
            end,
            initialize_ncsi_channel = function ()
                return nil
            end,
            update_ncsi_properties = function ()
                return nil
            end,
            next_tick = function ()
                return nil
            end
        }
    }
    c_network_adapter.update_network_adapter = function ()
        return nil
    end
    c_network_adapter.package_id = 0
    c_network_adapter.Type = 'test'
    c_network_adapter.Model = 'BF3'
    pcall(c_network_adapter.update_ncsi_properties, c_network_adapter, ports)
    lu.assertEquals(ports['BF3'].package_id, 0)
end

function TEST_network_adapter:test_set_npu_max_sfp_temp()
    local c_next_tick = c_network_adapter.next_tick
    local c_update_npu_max_sfp_temp = c_network_adapter.update_npu_max_sfp_temp
    c_network_adapter.update_npu_max_sfp_temp = function ()
        error('end')
    end
    c_network_adapter.next_tick = function(_, cb)
        return cb()
    end
    local ok, _ = pcall(function()
        return c_network_adapter:set_npu_max_sfp_temp()
    end)
    c_network_adapter.next_tick = c_next_tick
    c_network_adapter.update_npu_max_sfp_temp = c_update_npu_max_sfp_temp
    lu.assertEquals(ok, false)
end

function TEST_network_adapter:test_update_npu_max_sfp_temp()
    local ops = {
        { ReadingCelsius = 20 }, { ReadingCelsius = 40 }, { ReadingCelsius = 10 }, { ReadingCelsius = 0 }
    }
    c_network_adapter:update_npu_max_sfp_temp(ops)
    lu.assertEquals(c_network_adapter.SFPMaxTemperatureCelsius, 40)

    ops = { 
        { ReadingCelsius = 20, npu_om_not_present = false, npu_optical_module_info_abnormal = true }
    }
    c_network_adapter.TemperatureStatus = 0
    c_network_adapter:update_npu_max_sfp_temp(ops)
    lu.assertEquals(c_network_adapter.TemperatureStatus, 12)
end

function TEST_network_adapter:test_update_bdf()
    c_network_adapter.Bus = 1
    c_network_adapter.Device = 2
    c_network_adapter.Function = 3
    c_network_adapter:update_root_bdf()
    lu.assertEquals(c_network_adapter.RootBDF, '0000:01:02.3')
end

local pcie_info = {
    system_id = 1,
    is_local = false,
    cpu_id = 1,
    bus_num = 1,
    device_num = 1,
    function_num = 1,
    did = 0,
    vid = 0,
    sdid = 0,
    svid = 0
}

-- 测试四元组信息解析成功
function TEST_network_adapter:test_parse_quater_info_succ()
    pmu_cmd.get_info_from_pmu = function()
        return {0xe5, 0x19, 0x20, 0xd1}
    end
    c_network_adapter:get_vid_did_svid_sdid(pcie_info)
    lu.assertEquals(pcie_info.did, 0xd120)
    lu.assertEquals(pcie_info.svid, 0x19e5)
end

-- 测试四元组信息校验失败
function TEST_network_adapter:test_update_quater_info_fail()
    pmu_cmd.get_info_from_pmu = function()
        return {0xff, 0xff, 0xff, 0xff}
    end
    local ret = c_network_adapter:verify_vid_did_svid_sdid(pcie_info)
    lu.assertIsFalse(ret)
end

-- 测试获取四元组信息
function TEST_network_adapter:test_update_quater_info()
    pmu_cmd.get_info_from_pmu = function()
        return {0xff, 0xff, 0xff, 0xff}
    end
    local ret = c_network_adapter:get_vid_did_svid_sdid(pcie_info)
    lu.assertIsFalse(ret)

    pmu_cmd.get_info_from_pmu = function()
        return {0xe5, 0x19, 0x20, 0xd1}
    end
    ret = c_network_adapter:get_vid_did_svid_sdid(pcie_info)
    lu.assertEquals(pcie_info.did, 0xd120)
    lu.assertIsTrue(ret)
end

-- 测试四元组信息校验成功
function TEST_network_adapter:test_verify_quater_info()
    pmu_cmd.get_info_from_pmu = function()
        return {0xe5, 0x19, 0x20, 0xd1}
    end
    pcie_info.sdid = 0
    local ret = c_network_adapter:verify_vid_did_svid_sdid(pcie_info)
    lu.assertIsTrue(ret)
    lu.assertNotEquals(pcie_info.sdid, 0xd120)
end

function TEST_network_adapter:test_record_nic_os_status_change()
    -- 状态变化上报日志
    local current_os_status = 5
    local last_os_status = 0
    c_network_adapter:record_nic_os_status_change(current_os_status, last_os_status)
    -- 状态未变化无操作
    local current_os_status = 5
    local last_os_status = 5
    c_network_adapter:record_nic_os_status_change(current_os_status, last_os_status)
end

function TEST_network_adapter:test_set_bios_boot_wait_flag()
    local bios_boot_wait_flag = 1
    c_network_adapter:set_bios_boot_wait_flag(bios_boot_wait_flag)
end

function TEST_network_adapter:test_get_dpu_os_status()
    c_network_adapter:get_dpu_os_status()
end

function TEST_network_adapter:test_fetch_dpu_os_status_by_ncsi_failed()
    c_network_adapter.ncsi_config_obj = nil
    c_network_adapter:fetch_dpu_os_status_by_ncsi()
end

mock_func = {}

local function mock_backup()
    mock_func.get_info_from_pmu = pmu_cmd.get_info_from_pmu
    mock_func.fork = skynet.fork
    mock_func.bdf_to_phy_addr = mctp_lib.bdf_to_phy_addr
    mock_func.get_endpoint_and_transport = mctp_lib.get_endpoint_and_transport
    mock_func.get_instance = c_object_manage.get_instance
end

local function mock_restore()
    pmu_cmd.get_info_from_pmu = mock_func.get_info_from_pmu
    skynet.fork = mock_func.fork
    mctp_lib.bdf_to_phy_addr = mock_func.bdf_to_phy_addr
    mctp_lib.get_endpoint_and_transport = mock_func.get_endpoint_and_transport
    c_object_manage.get_instance = mock_func.get_instance
end

local function mock_prepare_1()
    pmu_cmd.get_info_from_pmu = function()
        return {0x0c, 0xc1, 0xc2, 0x04}
    end
    skynet.fork = function(cb)
        cb()
    end
    mctp_lib.bdf_to_phy_addr = function(dev_bus)
        return dev_bus
    end
    mctp_lib.get_endpoint_and_transport = function()
        return 'endpoint', 'transport'
    end
    c_object_manage.get_instance = function()
        return {}
    end
end

local function mock_prepare_2()
    pmu_cmd.get_info_from_pmu = function()
        return {0x0c, nil, 0xc2, 0x04}
    end
end

local function mock_prepare_3()
    pmu_cmd.get_info_from_pmu = function()
        return 
    end
end

local function mock_prepare_4()
    pmu_cmd.get_info_from_pmu = function()
        return {0x0c, 0xc1, 0xc2, 0x04}
    end
    mctp_lib.get_endpoint_and_transport = function()
        return nil, nil
    end
end

function TEST_network_adapter:test_loop_bus_create_mctp_endpoint()
    mock_backup()
    mock_prepare_1()

    c_network_adapter.Model = 'BF3'
    c_network_adapter.transports = {}
    c_network_adapter.mctp_endpoints = {}
    local msg_type = 3
    local endpoint = c_network_adapter:create_mctp_endpoint(msg_type)
    lu.assertEquals(endpoint, 'endpoint')

    mock_prepare_2()
    local ok_2, endpoint_2 = pcall(function()
        return c_network_adapter:create_mctp_endpoint(msg_type)
    end)
    lu.assertEquals(ok_2, false)
    lu.assertNotEquals(endpoint_2, 'endpoint')

    mock_prepare_3()
    local ok_3, endpoint_3 = pcall(function()
        return c_network_adapter:create_mctp_endpoint(msg_type)
    end)
    lu.assertEquals(ok_3, false)
    lu.assertNotEquals(endpoint_3, 'endpoint')

    mock_prepare_4()
    local ok_4, endpoint_4 = pcall(function()
        return c_network_adapter:create_mctp_endpoint(msg_type)
    end)
    lu.assertEquals(ok_4, false)
    lu.assertNotEquals(endpoint_4, 'endpoint')

    mock_restore()
end

-- 测试通过pldm协议更新信息
function TEST_network_adapter:test_init_pldm()
    c_network_adapter:ctor()
    c_network_adapter.Model = 'QLE2742'
    c_network_adapter.SupportedMctp = true
    c_network_adapter.DevBus = 1
    c_network_adapter.DevDevice = 0
    c_network_adapter.DevFunction = 0
    local create_endpoint = c_network_adapter.create_mctp_endpoint
    c_network_adapter.create_mctp_endpoint = function ()
        return {}
    end
    local next_tick = c_network_adapter.next_tick
    c_network_adapter.next_tick = function (_, cb, ...)
        cb(...)
    end
    c_network_adapter:synchronize_port_bdf(2, 2)
    for _, v in pairs(c_network_adapter.pldm_schedulers) do
        pcall(function ()
            v.on_data_change:emit(0x00)
        end)
    end
    for _, v in pairs(c_network_adapter.pldm_schedulers) do
        pcall(function ()
            v.on_data_change:emit()
        end
    )
    end
    utils.msleep(1000)
    lu.assertNotEquals(c_network_adapter.pldm_config_obj, nil)
    c_network_adapter.next_tick = next_tick
    c_network_adapter.create_mctp_endpoint = create_endpoint
end

-- 测试停止pldm协议例测任务
function TEST_network_adapter:test_stop_schedulers()
    c_network_adapter.ncsi_schedulers = {
        schedulers = {
            deconstruct = function()
            end
        }
    }
    c_network_adapter:stop()
    lu.assertEquals(c_network_adapter.pldm_schedulers, {})
    lu.assertEquals(c_network_adapter.smbus_schedulers, {})
    lu.assertEquals(c_network_adapter.ncsi_schedulers, {})
end

function TEST_network_adapter:test_update_port_mac()
    local port = {
        WorkloadType = 1,
        PortID = 1,
        MACAddress = "11:11:11:11:11:11"
    }
    local mac_info = {
        {
            [1] = 1,
            [3] = "22:22:22:22:22:22"
        }
    }
    c_network_adapter.update_port_mac_action(mac_info, port)
end

-- 测试 update_port_wwnn_by_pldm 日志输出
function TEST_network_adapter:test_update_port_wwnn_by_pldm_log()
    local log = require('mc.logging')
    local original_notice = log.notice
    local original_NodeId = c_network_adapter.NodeId
    local original_pldm_schedulers = c_network_adapter.pldm_schedulers
    local original_pldm_config_obj = c_network_adapter.pldm_config_obj
    local log_calls = {}
    
    log.notice = function(self, fmt, ...)
        table.insert(log_calls, {fmt = fmt, args = {...}})
    end
    
    c_network_adapter.NodeId = "TestAdapter"
    c_network_adapter.pldm_schedulers = {}
    c_network_adapter.pldm_config_obj = {
        DefaultWWNN = function()
            return {
                on_data_change = { on = function() end },
                start = function() end
            }
        end,
        WorkWWNN = function()
            return {
                on_data_change = { on = function() end },
                start = function() end
            }
        end
    }
    
    c_network_adapter:update_port_wwnn_by_pldm({})
    
    lu.assertEquals(#log_calls, 2)
    lu.assertEquals(log_calls[1].fmt, '%s update default_wwnn by pldm start')
    lu.assertEquals(log_calls[1].args[1], "TestAdapter")
    lu.assertEquals(log_calls[2].fmt, '%s update work_wwnn by pldm start')
    lu.assertEquals(log_calls[2].args[1], "TestAdapter")
    
    log.notice = original_notice
    c_network_adapter.NodeId = original_NodeId
    c_network_adapter.pldm_schedulers = original_pldm_schedulers
    c_network_adapter.pldm_config_obj = original_pldm_config_obj
end

-- 测试 update_port_wwpn_by_pldm 日志输出
function TEST_network_adapter:test_update_port_wwpn_by_pldm_log()
    local log = require('mc.logging')
    local original_notice = log.notice
    local original_NodeId = c_network_adapter.NodeId
    local original_pldm_schedulers = c_network_adapter.pldm_schedulers
    local original_pldm_config_obj = c_network_adapter.pldm_config_obj
    local log_calls = {}
    
    log.notice = function(self, fmt, ...)
        table.insert(log_calls, {fmt = fmt, args = {...}})
    end
    
    c_network_adapter.NodeId = "TestAdapter"
    c_network_adapter.pldm_schedulers = {}
    c_network_adapter.pldm_config_obj = {
        Port1DefaultWWPN = function()
            return {
                on_data_change = { on = function() end },
                start = function() end
            }
        end,
        Port1WorkWWPN = function()
            return {
                on_data_change = { on = function() end },
                start = function() end
            }
        end
    }
    
    c_network_adapter:update_port_wwpn_by_pldm(1, {})
    
    lu.assertEquals(#log_calls, 2)
    lu.assertEquals(log_calls[1].fmt, '%s update default_wwpn by pldm start, port_id:%s')
    lu.assertEquals(log_calls[1].args[1], "TestAdapter")
    lu.assertEquals(log_calls[1].args[2], 1)
    lu.assertEquals(log_calls[2].fmt, '%s update work_wwpn by pldm start, port_id:%s')
    lu.assertEquals(log_calls[2].args[1], "TestAdapter")
    lu.assertEquals(log_calls[2].args[2], 1)
    
    log.notice = original_notice
    c_network_adapter.NodeId = original_NodeId
    c_network_adapter.pldm_schedulers = original_pldm_schedulers
    c_network_adapter.pldm_config_obj = original_pldm_config_obj
end

-- 测试 update_port_link_status_by_pldm 函数
function TEST_network_adapter:test_update_port_link_status_by_pldm()
    local log = require('mc.logging')
    local original_error = log.error
    local original_NodeId = c_network_adapter.NodeId
    local original_pldm_schedulers = c_network_adapter.pldm_schedulers
    local original_pldm_config_obj = c_network_adapter.pldm_config_obj
    local error_called = false
    local mock_scheduler = {}
    
    log.error = function(self, fmt, ...)
        error_called = true
    end
    
    c_network_adapter.NodeId = "TestAdapter"
    c_network_adapter.pldm_schedulers = {}
    c_network_adapter.pldm_config_obj = {
        Port1LinkStatus = function() return mock_scheduler end
    }
    
    mock_scheduler.on_data_change = { on = function(self, cb) mock_scheduler.data_cb = cb end }
    mock_scheduler.on_error = { on = function(self, cb) mock_scheduler.error_cb = cb end }
    mock_scheduler.start = function() end
    
    local test_port = {
        PortID = 1,
        get_properties_res = {},
        set_link_status = function() end,
        set_link_status_numeric = function() end
    }
    
    c_network_adapter:update_port_link_status_by_pldm(1, {test_port})
    
    -- 测试数据变化
    mock_scheduler.data_cb({LinkStatus = "Up", SpeedMbps = 1000, SpeedGbps = 1})
    lu.assertTrue(test_port.get_properties_res.LinkStatusFromPldm)
    
    -- 测试错误回调
    test_port.get_properties_res.LinkStatusFromPldm = true
    mock_scheduler.error_cb()
    lu.assertFalse(test_port.get_properties_res.LinkStatusFromPldm)
    lu.assertTrue(error_called)
    
    log.error = original_error
    c_network_adapter.NodeId = original_NodeId
    c_network_adapter.pldm_schedulers = original_pldm_schedulers
    c_network_adapter.pldm_config_obj = original_pldm_config_obj
end

-- 测试 update_chip_temp_by_pldm 函数
function TEST_network_adapter:test_update_chip_temp_by_pldm()
    local log = require('mc.logging')
    local original_error = log.error
    local original_NodeId = c_network_adapter.NodeId
    local original_pldm_schedulers = c_network_adapter.pldm_schedulers
    local original_pldm_config_obj = c_network_adapter.pldm_config_obj
    local original_get_properties_res = c_network_adapter.get_properties_res
    local error_called = false
    local mock_scheduler = {}
    
    log.error = function(self, fmt, ...)
        error_called = true
    end
    
    c_network_adapter.NodeId = "TestAdapter"
    c_network_adapter.pldm_schedulers = {}
    c_network_adapter.get_properties_res = {}
    c_network_adapter.pldm_config_obj = {
        ChipTemp = function() return mock_scheduler end
    }
    
    mock_scheduler.on_data_change = { on = function(self, cb) mock_scheduler.data_cb = cb end }
    mock_scheduler.on_error = { on = function(self, cb) mock_scheduler.error_cb = cb end }
    mock_scheduler.start = function() end
    
    c_network_adapter:update_chip_temp_by_pldm()
    
    -- 测试数据变化
    mock_scheduler.data_cb(45)
    lu.assertTrue(c_network_adapter.get_properties_res.ChipTempFromPldm)
    lu.assertEquals(c_network_adapter.TemperatureCelsius, 45)
    
    -- 测试错误回调
    c_network_adapter.get_properties_res.ChipTempFromPldm = true
    mock_scheduler.error_cb()
    lu.assertFalse(c_network_adapter.get_properties_res.ChipTempFromPldm)
    lu.assertTrue(error_called)
    
    log.error = original_error
    c_network_adapter.NodeId = original_NodeId
    c_network_adapter.pldm_schedulers = original_pldm_schedulers
    c_network_adapter.pldm_config_obj = original_pldm_config_obj
    c_network_adapter.get_properties_res = original_get_properties_res
end

-- 测试 update_link_status_by_pldm 函数
function TEST_network_adapter:test_update_link_status_by_pldm()
    local log = require('mc.logging')
    local original_error = log.error
    local original_NodeId = c_network_adapter.NodeId
    local original_pldm_schedulers = c_network_adapter.pldm_schedulers
    local original_pldm_config_obj = c_network_adapter.pldm_config_obj
    local error_called = false
    local mock_scheduler = {}
    
    log.error = function(self, fmt, ...)
        error_called = true
    end
    
    c_network_adapter.NodeId = "TestAdapter"
    c_network_adapter.pldm_schedulers = {}
    c_network_adapter.pldm_config_obj = {
        Port1LinkStatus = function() return mock_scheduler end
    }
    
    mock_scheduler.on_data_change = { on = function(self, cb) mock_scheduler.data_cb = cb end }
    mock_scheduler.on_error = { on = function(self, cb) mock_scheduler.error_cb = cb end }
    mock_scheduler.start = function() end
    
    local test_port = {
        PortID = 1,
        NodeId = "TestPort1",
        get_properties_res = {}
    }
    
    c_network_adapter:update_link_status_by_pldm(1, {test_port})
    
    -- 测试数据变化
    mock_scheduler.data_cb("Up")
    lu.assertTrue(test_port.get_properties_res.LinkStatusFromPldm)
    lu.assertEquals(test_port.LinkStatus, "Up")
    
    -- 测试错误回调
    test_port.get_properties_res.LinkStatusFromPldm = true
    mock_scheduler.error_cb()
    lu.assertFalse(test_port.get_properties_res.LinkStatusFromPldm)
    lu.assertTrue(error_called)
    
    log.error = original_error
    c_network_adapter.NodeId = original_NodeId
    c_network_adapter.pldm_schedulers = original_pldm_schedulers
    c_network_adapter.pldm_config_obj = original_pldm_config_obj
end

-- 测试 update_fault_code 函数
function TEST_network_adapter:test_update_fault_code()
    local log = require('mc.logging')
    local original_notice = log.notice
    local original_NodeId = c_network_adapter.NodeId
    local original_smbus_schedulers = c_network_adapter.smbus_schedulers
    local original_smbus_config_obj = c_network_adapter.smbus_config_obj
    local notice_calls = {}
    local mock_scheduler = {}
    
    log.notice = function(self, fmt, ...)
        table.insert(notice_calls, {fmt = fmt, args = {...}})
    end
    
    c_network_adapter.NodeId = "TestAdapter"
    c_network_adapter.smbus_schedulers = {}
    c_network_adapter.health = 1
    c_network_adapter.smbus_config_obj = {
        FaultCode = function() return mock_scheduler end
    }
    
    mock_scheduler.on_data_change = { on = function(self, cb) mock_scheduler.data_cb = cb end }
    mock_scheduler.start = function() end
    
    c_network_adapter:update_fault_code()
    
    -- 测试启动日志
    lu.assertEquals(#notice_calls, 1)
    lu.assertEquals(notice_calls[1].fmt, '%s update fault code by smbus start')
    lu.assertEquals(notice_calls[1].args[1], "TestAdapter")
    
    -- 测试数据变化
    mock_scheduler.data_cb({123})
    lu.assertEquals(#notice_calls, 2)
    lu.assertEquals(notice_calls[2].fmt, '%s update fault state to %s by smbus')
    lu.assertEquals(notice_calls[2].args[1], "TestAdapter")
    lu.assertEquals(notice_calls[2].args[2], 123)
    
    log.notice = original_notice
    c_network_adapter.NodeId = original_NodeId
    c_network_adapter.smbus_schedulers = original_smbus_schedulers
    c_network_adapter.smbus_config_obj = original_smbus_config_obj
end

-- 测试 update_health 函数
function TEST_network_adapter:test_update_health()
    local log = require('mc.logging')
    local original_notice = log.notice
    local original_error = log.error
    local original_NodeId = c_network_adapter.NodeId
    local original_smbus_schedulers = c_network_adapter.smbus_schedulers
    local original_smbus_config_obj = c_network_adapter.smbus_config_obj
    local original_health = c_network_adapter.health
    local log_calls = {}
    local mock_scheduler = {}
    
    log.notice = function(self, fmt, ...) table.insert(log_calls, {type='notice', fmt=fmt, args={...}}) end
    log.error = function(self, fmt, ...) table.insert(log_calls, {type='error', fmt=fmt, args={...}}) end
    
    c_network_adapter.NodeId = "TestAdapter"
    c_network_adapter.smbus_schedulers = {}
    c_network_adapter.health = 0
    c_network_adapter.smbus_config_obj = { Health = function() return mock_scheduler end }
    
    mock_scheduler.on_data_change = { on = function(self, cb) mock_scheduler.data_cb = cb end }
    mock_scheduler.start = function() end
    
    c_network_adapter:update_health()
    
    -- update_health 方法没有启动日志，直接测试数据变化
    lu.assertEquals(#log_calls, 0) -- 没有启动日志
    
    -- 测试数据变化 - 正常状态
    mock_scheduler.data_cb(0)
    lu.assertEquals(c_network_adapter.health, 0)
    lu.assertEquals(#log_calls, 0) -- 没有错误日志
    
    -- 测试数据变化 - 异常状态
    mock_scheduler.data_cb(1)
    lu.assertEquals(c_network_adapter.health, 1)
    lu.assertEquals(#log_calls, 1)
    lu.assertEquals(log_calls[1].type, 'error')
    lu.assertEquals(log_calls[1].fmt, 'card:%s, is not in normal state, health_status: %s')
    lu.assertEquals(log_calls[1].args[1], "TestAdapter")
    lu.assertEquals(log_calls[1].args[2], 1)
    
    log.notice = original_notice
    log.error = original_error
    c_network_adapter.NodeId = original_NodeId
    c_network_adapter.smbus_schedulers = original_smbus_schedulers
    c_network_adapter.smbus_config_obj = original_smbus_config_obj
    c_network_adapter.health = original_health
end

-- 测试 update_chip_temp 函数 (smbus版本)
function TEST_network_adapter:test_update_chip_temp_smbus()
    local log = require('mc.logging')
    local original_notice = log.notice
    local original_error = log.error
    local original_NodeId = c_network_adapter.NodeId
    local original_smbus_schedulers = c_network_adapter.smbus_schedulers
    local original_smbus_config_obj = c_network_adapter.smbus_config_obj
    local original_get_properties_res = c_network_adapter.get_properties_res
    local log_calls = {}
    local mock_scheduler = {}
    
    log.notice = function(self, fmt, ...) table.insert(log_calls, {type='notice', fmt=fmt, args={...}}) end
    log.error = function(self, fmt, ...) table.insert(log_calls, {type='error', fmt=fmt, args={...}}) end
    
    c_network_adapter.NodeId = "TestAdapter"
    c_network_adapter.smbus_schedulers = {}
    c_network_adapter.get_properties_res = {}
    c_network_adapter.smbus_config_obj = { ChipTemp = function() return mock_scheduler end }
    
    mock_scheduler.on_data_change = { on = function(self, cb) mock_scheduler.data_cb = cb end }
    mock_scheduler.on_error = { on = function(self, cb) mock_scheduler.error_cb = cb end }
    mock_scheduler.start = function() end
    
    c_network_adapter:update_chip_temp()
    
    -- 测试启动日志
    lu.assertEquals(log_calls[1].fmt, '%s update chip temp by smbus start')
    lu.assertEquals(log_calls[1].args[1], "TestAdapter")
    
    -- 测试数据变化（没有日志输出）
    mock_scheduler.data_cb(55)
    lu.assertTrue(c_network_adapter.get_properties_res.ChipTempFromSmbus)
    lu.assertEquals(c_network_adapter.TemperatureCelsius, 55)
    
    -- 测试错误回调
    c_network_adapter.get_properties_res.ChipTempFromSmbus = true
    mock_scheduler.error_cb()
    lu.assertFalse(c_network_adapter.get_properties_res.ChipTempFromSmbus)
    lu.assertEquals(#log_calls, 2)
    lu.assertEquals(log_calls[2].fmt, '%s update chip temp by smbus on_error')
    
    log.notice = original_notice
    log.error = original_error
    c_network_adapter.NodeId = original_NodeId
    c_network_adapter.smbus_schedulers = original_smbus_schedulers
    c_network_adapter.smbus_config_obj = original_smbus_config_obj
    c_network_adapter.get_properties_res = original_get_properties_res
end

-- 测试 update_optical_temp 函数 (smbus版本)
function TEST_network_adapter:test_update_optical_temp_smbus()
    local log = require('mc.logging')
    local original_debug = log.debug
    local original_error = log.error
    local original_notice = log.notice
    local original_NodeId = c_network_adapter.NodeId
    local original_smbus_schedulers = c_network_adapter.smbus_schedulers
    local original_smbus_config_obj = c_network_adapter.smbus_config_obj
    local log_calls = {}
    local mock_scheduler = {}
    
    log.debug = function(self, fmt, ...) table.insert(log_calls, {type='debug', fmt=fmt, args={...}}) end
    log.error = function(self, fmt, ...) table.insert(log_calls, {type='error', fmt=fmt, args={...}}) end
    log.notice = function(self, fmt, ...) table.insert(log_calls, {type='notice', fmt=fmt, args={...}}) end
    
    c_network_adapter.NodeId = "TestAdapter"
    c_network_adapter.smbus_schedulers = {}
    c_network_adapter.smbus_config_obj = { OpticalTemp = function() return mock_scheduler end }
    
    mock_scheduler.on_data_change = { on = function(self, cb) mock_scheduler.data_cb = cb end }
    mock_scheduler.on_error = { on = function(self, cb) mock_scheduler.error_cb = cb end }
    mock_scheduler.start = function() end
    
    local test_ports = {{
        NodeId = "Port1", 
        get_properties_res = {}, 
        set_op_temp = function() end, 
        connect_signal = function() end
    }}
    c_network_adapter:update_optical_temp(test_ports)
    
    -- 测试启动日志
    lu.assertEquals(log_calls[1].fmt, '%s update optical temp by smbus start')
    lu.assertEquals(log_calls[1].args[1], "TestAdapter")
    
    -- 测试错误回调
    test_ports[1].get_properties_res.OpticalTempFromSmbus = true
    mock_scheduler.error_cb()
    lu.assertFalse(test_ports[1].get_properties_res.OpticalTempFromSmbus)
    lu.assertEquals(#log_calls, 2)
    lu.assertEquals(log_calls[2].fmt, '%s update optical temp by smbus on_error')
    
    log.debug = original_debug
    log.error = original_error
    log.notice = original_notice
    c_network_adapter.NodeId = original_NodeId
    c_network_adapter.smbus_schedulers = original_smbus_schedulers
    c_network_adapter.smbus_config_obj = original_smbus_config_obj
end

-- 测试 update_smbus_link_status 函数
function TEST_network_adapter:test_update_smbus_link_status()
    local log = require('mc.logging')
    local original_notice = log.notice
    local original_error = log.error
    local original_NodeId = c_network_adapter.NodeId
    local original_smbus_schedulers = c_network_adapter.smbus_schedulers
    local original_smbus_config_obj = c_network_adapter.smbus_config_obj
    local log_calls = {}
    local mock_scheduler = {}
    
    log.notice = function(self, fmt, ...) table.insert(log_calls, {type='notice', fmt=fmt, args={...}}) end
    log.error = function(self, fmt, ...) table.insert(log_calls, {type='error', fmt=fmt, args={...}}) end
    
    c_network_adapter.NodeId = "TestAdapter"
    c_network_adapter.smbus_schedulers = {}
    c_network_adapter.smbus_config_obj = { LinkStatus = function() return mock_scheduler end }
    
    mock_scheduler.on_data_change = { on = function(self, cb) mock_scheduler.data_cb = cb end }
    mock_scheduler.on_error = { on = function(self, cb) mock_scheduler.error_cb = cb end }
    mock_scheduler.start = function() end
    
    local test_ports = {{
        NodeId = "Port1", 
        get_properties_res = {}, 
        set_link_status = function() end, 
        set_link_status_numeric = function() end, 
        connect_signal = function() end
    }}
    c_network_adapter:update_smbus_link_status(test_ports)
    
    -- 测试启动日志
    lu.assertEquals(log_calls[1].fmt, '%s update link status by smbus start')
    lu.assertEquals(log_calls[1].args[1], "TestAdapter")
    
    -- 测试错误回调
    test_ports[1].get_properties_res.LinkStatusFromSmbus = true
    mock_scheduler.error_cb()
    lu.assertFalse(test_ports[1].get_properties_res.LinkStatusFromSmbus)
    lu.assertEquals(#log_calls, 2)
    lu.assertEquals(log_calls[2].fmt, '%s update link status by smbus on_error')
    
    log.notice = original_notice
    log.error = original_error
    c_network_adapter.NodeId = original_NodeId
    c_network_adapter.smbus_schedulers = original_smbus_schedulers
    c_network_adapter.smbus_config_obj = original_smbus_config_obj
end

-- 测试 update_smbus_mac_address 函数
function TEST_network_adapter:test_update_smbus_mac_address()
    local log = require('mc.logging')
    local original_notice = log.notice
    local original_NodeId = c_network_adapter.NodeId
    local original_smbus_schedulers = c_network_adapter.smbus_schedulers
    local original_smbus_config_obj = c_network_adapter.smbus_config_obj
    local log_calls = {}
    local mock_scheduler = {}
    
    log.notice = function(self, fmt, ...) table.insert(log_calls, {fmt=fmt, args={...}}) end
    
    c_network_adapter.NodeId = "TestAdapter"
    c_network_adapter.smbus_schedulers = {}
    c_network_adapter.smbus_config_obj = { MacAddress = function() return mock_scheduler end }
    
    mock_scheduler.on_data_change = { on = function(self, cb) mock_scheduler.data_cb = cb end }
    mock_scheduler.start = function() end
    
    local test_ports = {{
        NodeId = "Port1", 
        set_mac_addr = function() end, 
        set_permanent_mac_addr = function() end, 
        connect_signal = function() end
    }}
    c_network_adapter:update_smbus_mac_address(test_ports)
    
    -- 测试启动日志
    lu.assertEquals(log_calls[1].fmt, '%s update mac address by smbus start')
    lu.assertEquals(log_calls[1].args[1], "TestAdapter")
    
    log.notice = original_notice
    c_network_adapter.NodeId = original_NodeId
    c_network_adapter.smbus_schedulers = original_smbus_schedulers
    c_network_adapter.smbus_config_obj = original_smbus_config_obj
end

-- 测试 update_ncsi_firmware 函数
function TEST_network_adapter:test_update_ncsi_firmware()
    local log = require('mc.logging')
    local original_notice = log.notice
    local original_NodeId = c_network_adapter.NodeId
    local original_ncsi_schedulers = c_network_adapter.ncsi_schedulers
    local original_ncsi_config_obj = c_network_adapter.ncsi_config_obj
    local original_package_id = c_network_adapter.package_id
    local original_VendorID = c_network_adapter.VendorID
    local log_calls = {}
    local mock_scheduler = {}
    
    log.notice = function(self, fmt, ...) table.insert(log_calls, {fmt=fmt, args={...}}) end
    
    c_network_adapter.NodeId = "TestAdapter"
    c_network_adapter.ncsi_schedulers = {}
    c_network_adapter.package_id = 1
    c_network_adapter.VendorID = ""
    c_network_adapter.ncsi_config_obj = { 
        VendorID = function(params) return mock_scheduler end 
    }
    
    mock_scheduler.on_data_change = { on = function(self, cb) mock_scheduler.data_cb = cb end }
    mock_scheduler.start = function() end
    
    local test_ports = {{set_firmware_version = function() end}}
    c_network_adapter:update_ncsi_firmware(test_ports)
    
    -- 测试启动日志
    lu.assertEquals(log_calls[1].fmt, '%s update firmware version by ncsi start')
    lu.assertEquals(log_calls[1].args[1], "TestAdapter")
    
    -- 测试数据变化
    mock_scheduler.data_cb({FirmwareVersion = "v1.2.3"})
    lu.assertEquals(#log_calls, 2)
    lu.assertEquals(log_calls[2].fmt, '%s update firmware version to %s by ncsi')
    lu.assertEquals(log_calls[2].args[1], "TestAdapter")
    lu.assertEquals(log_calls[2].args[2], "v1.2.3")
    lu.assertEquals(c_network_adapter.FirmwareVersion, "v1.2.3")
    
    log.notice = original_notice
    c_network_adapter.NodeId = original_NodeId
    c_network_adapter.ncsi_schedulers = original_ncsi_schedulers
    c_network_adapter.ncsi_config_obj = original_ncsi_config_obj
    c_network_adapter.package_id = original_package_id
    c_network_adapter.VendorID = original_VendorID
end

-- 测试 update_chip_temp_by_ncsi 函数
function TEST_network_adapter:test_update_chip_temp_by_ncsi()
    local log = require('mc.logging')
    local original_error = log.error
    local original_NodeId = c_network_adapter.NodeId
    local original_ncsi_schedulers = c_network_adapter.ncsi_schedulers
    local original_ncsi_config_obj = c_network_adapter.ncsi_config_obj
    local original_get_properties_res = c_network_adapter.get_properties_res
    local error_called = false
    local mock_scheduler = {}
    
    log.error = function(self, fmt, ...)
        error_called = true
    end
    
    c_network_adapter.NodeId = "TestAdapter"
    c_network_adapter.ncsi_schedulers = {}
    c_network_adapter.get_properties_res = {}
    c_network_adapter.ncsi_config_obj = { ChipTemp = function() return mock_scheduler end }
    
    mock_scheduler.on_data_change = { on = function(self, cb) mock_scheduler.data_cb = cb end }
    mock_scheduler.on_error = { on = function(self, cb) mock_scheduler.error_cb = cb end }
    mock_scheduler.start = function() end
    
    c_network_adapter:update_chip_temp_by_ncsi()
    
    -- 测试数据变化
    mock_scheduler.data_cb(50)
    lu.assertTrue(c_network_adapter.get_properties_res.ChipTempFromNcsi)
    
    -- 测试错误回调
    c_network_adapter.get_properties_res.ChipTempFromNcsi = true
    mock_scheduler.error_cb()
    lu.assertFalse(c_network_adapter.get_properties_res.ChipTempFromNcsi)
    lu.assertTrue(error_called)
    
    log.error = original_error
    c_network_adapter.NodeId = original_NodeId
    c_network_adapter.ncsi_schedulers = original_ncsi_schedulers
    c_network_adapter.ncsi_config_obj = original_ncsi_config_obj
    c_network_adapter.get_properties_res = original_get_properties_res
end

-- 测试 update_max_operating_temp_by_ncsi 函数
function TEST_network_adapter:test_update_max_operating_temp_by_ncsi()
    local log = require('mc.logging')
    local original_notice = log.notice
    local original_NodeId = c_network_adapter.NodeId
    local original_ncsi_config_obj = c_network_adapter.ncsi_config_obj
    local original_package_id = c_network_adapter.package_id
    local log_calls = {}
    
    log.notice = function(self, fmt, ...) table.insert(log_calls, {fmt=fmt, args={...}}) end
    
    c_network_adapter.NodeId = "TestAdapter"
    c_network_adapter.package_id = 1
    c_network_adapter.ncsi_config_obj = { 
        MaxOpTemp = function(params) 
            return { value = function() return 90 end }
        end 
    }
    
    c_network_adapter:update_max_operating_temp_by_ncsi()
    
    -- 测试日志输出
    lu.assertEquals(log_calls[1].fmt, '%s update max operating temperature to %s by ncsi')
    lu.assertEquals(log_calls[1].args[1], "TestAdapter")
    lu.assertEquals(log_calls[1].args[2], 90)
    lu.assertEquals(c_network_adapter.MaxOperatingTemperatureCelsius, 90)
    
    log.notice = original_notice
    c_network_adapter.NodeId = original_NodeId
    c_network_adapter.ncsi_config_obj = original_ncsi_config_obj
    c_network_adapter.package_id = original_package_id
end

-- 测试 update_error_code_by_ncsi 函数
function TEST_network_adapter:test_update_error_code_by_ncsi()
    local log = require('mc.logging')
    local original_notice = log.notice
    local original_NodeId = c_network_adapter.NodeId
    local original_ncsi_schedulers = c_network_adapter.ncsi_schedulers
    local original_ncsi_config_obj = c_network_adapter.ncsi_config_obj
    local original_package_id = c_network_adapter.package_id
    local log_calls = {}
    local mock_scheduler = {}
    
    log.notice = function(self, fmt, ...) table.insert(log_calls, {fmt=fmt, args={...}}) end
    
    c_network_adapter.NodeId = "TestAdapter"
    c_network_adapter.ncsi_schedulers = {}
    c_network_adapter.package_id = 1
    c_network_adapter.ncsi_config_obj = { 
        FaultStatCode = function(params) return mock_scheduler end 
    }
    
    mock_scheduler.on_data_change = { on = function(self, cb) mock_scheduler.data_cb = cb end }
    mock_scheduler.on_error = { on = function(self, cb) mock_scheduler.error_cb = cb end }
    mock_scheduler.start = function() end
    
    c_network_adapter:update_error_code_by_ncsi()
    
    -- 测试启动日志
    lu.assertEquals(log_calls[1].fmt, '%s update fault code by ncsi start')
    lu.assertEquals(log_calls[1].args[1], "TestAdapter")
    
    -- 测试数据变化 - 有错误码
    mock_scheduler.data_cb({health_status = 0, error_codes = {123}})
    lu.assertEquals(log_calls[2].fmt, '%s update fault state to %s by ncsi')
    lu.assertEquals(log_calls[2].args[1], "TestAdapter")
    lu.assertEquals(log_calls[2].args[2], 123)
    
    log.notice = original_notice
    c_network_adapter.NodeId = original_NodeId
    c_network_adapter.ncsi_schedulers = original_ncsi_schedulers
    c_network_adapter.ncsi_config_obj = original_ncsi_config_obj
    c_network_adapter.package_id = original_package_id
end

function TEST_network_adapter:test_update_port_bdf()
    local skynet = require 'skynet'
    local fructl = require 'infrastructure.fructl'
    local origin_sleep = skynet.sleep
    local origin_get_power_status = fructl.get_power_status
    local origin_verify_vid_did_svid_sdid = c_network_adapter.verify_vid_did_svid_sdid

    c_network_adapter.verify_vid_did_svid_sdid = function()
        return true
    end

    fructl.get_power_status = function()
        return 'ON'
    end
    
    skynet.sleep = function()
        return
    end

    c_network_adapter.DevBus = 0
    c_network_adapter.Type = 1
    c_network_adapter.SocketId = 1
    c_network_adapter.Bus = 5
    c_network_adapter.Device= 16
    local ports = {{PortID = 1, BDF = ''}}
    c_network_adapter:update_port_bdf(ports)
    lu.assertEquals(ports[1].BDF, '0000:06:10.1')
    c_network_adapter.verify_vid_did_svid_sdid = origin_verify_vid_did_svid_sdid
    skynet.sleep = origin_sleep
    fructl.get_power_status = origin_get_power_status
end

function TEST_network_adapter:test_update_smbios_status()
    local temp_collection = c_optical_module.collection
    c_optical_module.collection = {
        fetch = function(test)
            return {
                {
                    update_smbios_status = function(self, value)
                        c_network_adapter.smbios_status = value
                    end
                }    
            }
        end
    }

    c_network_adapter:update_smbios_status('TestStaus')
    c_optical_module.collection = temp_collection
    lu.assertEquals(c_network_adapter.smbios_status, 'TestStaus')
end

function TEST_network_adapter:test_gc_task()
    local skynet = require('skynet')
    local log = require('mc.logging')

    -- 备份原始函数
    local original_notice = log.notice
    local original_fork_loop = skynet.fork_loop
    local original_sleep = skynet.sleep

    local log_calls = {}

    -- 模拟log.notice来捕获调用
    log.notice = function(self, fmt, ...)
        table.insert(log_calls, { type = 'notice', fmt = fmt, args = { ... } })
    end

    -- 模拟skynet.sleep立即返回
    skynet.sleep = function()
        return
    end

    -- 模拟skynet.fork_loop，执行回调但避免无限循环
    skynet.fork_loop = function(config, callback)
        if callback then
            -- 创建模拟环境，防止while循环无限运行
            local sleep_count = 0
            local original_inner_sleep = skynet.sleep

            skynet.sleep = function(time)
                sleep_count = sleep_count + 1
                -- 第一次sleep后（触发我们要测试的日志消息），
                -- 抛出错误来跳出任何while循环
                if sleep_count > 1 then
                    error("Test break - avoiding infinite loop")
                end
            end

            -- 在保护模式下执行回调以捕获我们的测试中断
            local success, err = pcall(callback)

            -- 恢复内部的sleep函数
            skynet.sleep = original_inner_sleep

            -- 如果失败不是由于我们的测试中断，则重新抛出错误
            if not success and not string.find(err, "Test break") then
                error(err)
            end
        end
    end

    network_adapter_app:gc_task()

    local found_log = false
    for _, call in ipairs(log_calls) do
        if call.type == 'notice' and string.find(call.fmt, 'gc task start') then
            found_log = true
            break
        end
    end

    -- 恢复原始函数
    log.notice = original_notice
    skynet.fork_loop = original_fork_loop
    skynet.sleep = original_sleep

    lu.assertTrue(found_log)
end

-- 测试update_chip_temp_by_ncsi函数的NCSI恢复时停止SMBUS fallback逻辑
function TEST_network_adapter:test_update_chip_temp_by_ncsi_ncsi_recovered_stops_smbus_fallback()
    -- 备份原始状态
    local original_smbios_status = c_network_adapter.smbios_status
    local original_get_properties_res = c_network_adapter.get_properties_res
    local original_ncsi_schedulers = c_network_adapter.ncsi_schedulers
    local original_smbus_schedulers = c_network_adapter.smbus_schedulers
    local original_ncsi_config_obj = c_network_adapter.ncsi_config_obj
    local original_package_id = c_network_adapter.package_id
    
    -- 初始化测试状态
    c_network_adapter.smbios_status = 3
    c_network_adapter.get_properties_res = {}
    c_network_adapter.ncsi_schedulers = {}
    c_network_adapter.smbus_schedulers = {}
    
    -- 模拟SMBUS任务正在运行
    local smbus_task_paused = false
    c_network_adapter.smbus_schedulers.chip_temp_task = {
        is_paused = false,
        pause = function() smbus_task_paused = true end,
        data = "some_data"
    }
    
    -- 模拟NCSI配置对象
    local scheduler_mock = {
        on_data_change = {
            on = function(self, callback)
                self.callback = callback
            end
        },
        on_error = {
            on = function(self, callback)
                self.error_callback = callback
            end
        },
        start = function() end
    }
    
    c_network_adapter.ncsi_config_obj = {
        ChipTemp = function() return scheduler_mock end
    }
    c_network_adapter.package_id = 0
    
    -- 打桩外部依赖
    local original_table_insert = table.insert
    table.insert = function() end
    
    -- 执行函数
    c_network_adapter:update_chip_temp_by_ncsi()
    
    -- 模拟NCSI数据变化（恢复正常）
    local temp_value = 45
    scheduler_mock.on_data_change.callback(temp_value)
    
    -- 验证结果
    lu.assertEquals(c_network_adapter.TemperatureCelsius, temp_value)
    lu.assertEquals(c_network_adapter.TemperatureStatus, 0)
    lu.assertTrue(c_network_adapter.get_properties_res.ChipTempFromNcsi)
    lu.assertTrue(smbus_task_paused)
    lu.assertNil(c_network_adapter.smbus_schedulers.chip_temp_task.data)
    
    -- 还原打桩
    table.insert = original_table_insert
    
    -- 还原全局状态
    c_network_adapter.smbios_status = original_smbios_status
    c_network_adapter.get_properties_res = original_get_properties_res
    c_network_adapter.ncsi_schedulers = original_ncsi_schedulers
    c_network_adapter.smbus_schedulers = original_smbus_schedulers
    c_network_adapter.ncsi_config_obj = original_ncsi_config_obj
    c_network_adapter.package_id = original_package_id
end

-- 测试update_chip_temp_by_ncsi函数的NCSI失败时启动SMBUS fallback逻辑
function TEST_network_adapter:test_update_chip_temp_by_ncsi_ncsi_failed_activates_smbus_fallback()
    -- 备份原始状态
    local original_get_properties_res = c_network_adapter.get_properties_res
    local original_ncsi_schedulers = c_network_adapter.ncsi_schedulers
    local original_smbus_schedulers = c_network_adapter.smbus_schedulers
    local original_ncsi_config_obj = c_network_adapter.ncsi_config_obj
    local original_package_id = c_network_adapter.package_id
    
    -- 初始化测试状态
    c_network_adapter.get_properties_res = {ChipTempFromNcsi = true}
    c_network_adapter.ncsi_schedulers = {}
    c_network_adapter.smbus_schedulers = {}
    
    -- 模拟SMBUS任务已暂停
    local smbus_task_resumed = false
    c_network_adapter.smbus_schedulers.chip_temp_task = {
        is_paused = true,
        resume = function() smbus_task_resumed = true end
    }
    
    -- 模拟NCSI配置对象
    local scheduler_mock = {
        on_data_change = {
            on = function(self, callback) 
                self.callback = callback
            end
        },
        on_error = {
            on = function(self, callback)
                self.error_callback = callback
            end
        },
        start = function() end
    }
    
    c_network_adapter.ncsi_config_obj = {
        ChipTemp = function() return scheduler_mock end
    }
    c_network_adapter.package_id = 0
    
    -- 打桩外部依赖
    local original_table_insert = table.insert
    table.insert = function() end
    
    -- 执行函数
    c_network_adapter:update_chip_temp_by_ncsi()
    
    -- 模拟NCSI连续失败达到阈值（NCSI_FAILED_THRESHOLD = 3）
    for i = 1, 3 do
        scheduler_mock.on_error.error_callback()
    end
    
    -- 验证结果
    lu.assertFalse(c_network_adapter.get_properties_res.ChipTempFromNcsi)
    lu.assertTrue(smbus_task_resumed)
    
    -- 还原打桩
    table.insert = original_table_insert
    
    -- 还原全局状态
    c_network_adapter.get_properties_res = original_get_properties_res
    c_network_adapter.ncsi_schedulers = original_ncsi_schedulers
    c_network_adapter.smbus_schedulers = original_smbus_schedulers
    c_network_adapter.ncsi_config_obj = original_ncsi_config_obj
    c_network_adapter.package_id = original_package_id
end

-- 测试update_error_code_by_ncsi函数的NCSI恢复时停止SMBUS fallback逻辑
function TEST_network_adapter:test_update_error_code_by_ncsi_ncsi_recovered_stops_smbus_fallback()
    -- 备份原始状态
    local original_smbus_collect_status = c_network_adapter.smbus_collect_status
    local original_get_properties_res = c_network_adapter.get_properties_res
    local original_ncsi_schedulers = c_network_adapter.ncsi_schedulers
    local original_smbus_schedulers = c_network_adapter.smbus_schedulers
    local original_ncsi_config_obj = c_network_adapter.ncsi_config_obj
    local original_package_id = c_network_adapter.package_id
    
    -- 初始化测试状态
    c_network_adapter.smbus_collect_status = 0 -- LOG_DUMP_IDLE
    c_network_adapter.get_properties_res = {}
    c_network_adapter.ncsi_schedulers = {}
    c_network_adapter.smbus_schedulers = {}
    
    -- 模拟SMBUS任务正在运行
    local smbus_task_paused = false
    c_network_adapter.smbus_schedulers.fault_code_task = {
        is_paused = false,
        pause = function() smbus_task_paused = true end,
        data = "some_data"
    }
    
    -- 模拟NCSI配置对象
    local scheduler_mock = {
        on_data_change = {
            on = function(self, callback)
                self.callback = callback
            end
        },
        on_error = {
            on = function(self, callback)
                self.error_callback = callback
            end
        },
        start = function() end
    }
    
    c_network_adapter.ncsi_config_obj = {
        FaultStatCode = function(params) return scheduler_mock end
    }
    c_network_adapter.package_id = 0
    
    -- 打桩外部依赖
    local original_table_insert = table.insert
    table.insert = function() end
    
    -- 执行函数
    c_network_adapter:update_error_code_by_ncsi()
    
    -- 模拟NCSI数据变化（恢复正常）
    local fault_data = {
        health_status = 0,
        error_codes = {}
    }
    scheduler_mock.on_data_change.callback(fault_data)
    
    -- 验证结果
    lu.assertEquals(c_network_adapter.FaultState, 0)
    lu.assertTrue(c_network_adapter.get_properties_res.FaultCodeFromNcsi)
    lu.assertTrue(smbus_task_paused)
    lu.assertNil(c_network_adapter.smbus_schedulers.fault_code_task.data)
    
    -- 还原打桩
    table.insert = original_table_insert
    
    -- 还原全局状态
    c_network_adapter.smbus_collect_status = original_smbus_collect_status
    c_network_adapter.get_properties_res = original_get_properties_res
    c_network_adapter.ncsi_schedulers = original_ncsi_schedulers
    c_network_adapter.smbus_schedulers = original_smbus_schedulers
    c_network_adapter.ncsi_config_obj = original_ncsi_config_obj
    c_network_adapter.package_id = original_package_id
end

-- 测试update_error_code_by_ncsi函数的NCSI失败时启动SMBUS fallback逻辑
function TEST_network_adapter:test_update_error_code_by_ncsi_ncsi_failed_activates_smbus_fallback()
    -- 备份原始状态
    local original_get_properties_res = c_network_adapter.get_properties_res
    local original_ncsi_schedulers = c_network_adapter.ncsi_schedulers
    local original_smbus_schedulers = c_network_adapter.smbus_schedulers
    local original_ncsi_config_obj = c_network_adapter.ncsi_config_obj
    local original_package_id = c_network_adapter.package_id
    
    -- 初始化测试状态
    c_network_adapter.get_properties_res = {FaultCodeFromNcsi = true}
    c_network_adapter.ncsi_schedulers = {}
    c_network_adapter.smbus_schedulers = {}
    
    -- 模拟SMBUS任务已暂停
    local smbus_task_resumed = false
    c_network_adapter.smbus_schedulers.fault_code_task = {
        is_paused = true,
        resume = function() smbus_task_resumed = true end
    }
    
    -- 模拟NCSI配置对象
    local scheduler_mock = {
        on_data_change = {
            on = function(self, callback)
                self.callback = callback
            end
        },
        on_error = {
            on = function(self, callback)
                self.error_callback = callback
            end
        },
        start = function() end
    }
    
    c_network_adapter.ncsi_config_obj = {
        FaultStatCode = function(params) return scheduler_mock end
    }
    c_network_adapter.package_id = 0
    
    -- 打桩外部依赖
    local original_table_insert = table.insert
    table.insert = function() end
    
    -- 执行函数
    c_network_adapter:update_error_code_by_ncsi()
    
    -- 模拟NCSI连续失败达到阈值（NCSI_FAILED_THRESHOLD = 3）
    for i = 1, 3 do
        scheduler_mock.on_error.error_callback()
    end
    
    -- 验证结果
    lu.assertFalse(c_network_adapter.get_properties_res.FaultCodeFromNcsi)
    lu.assertTrue(smbus_task_resumed)
    
    -- 还原打桩
    table.insert = original_table_insert
    
    -- 还原全局状态
    c_network_adapter.get_properties_res = original_get_properties_res
    c_network_adapter.ncsi_schedulers = original_ncsi_schedulers
    c_network_adapter.smbus_schedulers = original_smbus_schedulers
    c_network_adapter.ncsi_config_obj = original_ncsi_config_obj
    c_network_adapter.package_id = original_package_id
end

-- 测试当SMBUS任务已暂停时NCSI恢复不会重复暂停
function TEST_network_adapter:test_ncsi_recovered_when_smbus_already_paused()
    -- 备份原始状态
    local original_smbios_status = c_network_adapter.smbios_status
    local original_get_properties_res = c_network_adapter.get_properties_res
    local original_ncsi_schedulers = c_network_adapter.ncsi_schedulers
    local original_smbus_schedulers = c_network_adapter.smbus_schedulers
    local original_ncsi_config_obj = c_network_adapter.ncsi_config_obj
    local original_package_id = c_network_adapter.package_id
    
    -- 初始化测试状态
    c_network_adapter.smbios_status = 3
    c_network_adapter.get_properties_res = {}
    c_network_adapter.ncsi_schedulers = {}
    c_network_adapter.smbus_schedulers = {}
    
    -- 模拟SMBUS任务已暂停
    local pause_call_count = 0
    c_network_adapter.smbus_schedulers.chip_temp_task = {
        is_paused = true,
        pause = function() pause_call_count = pause_call_count + 1 end,
        data = "existing_data"
    }
    
    -- 模拟NCSI配置对象
    local scheduler_mock = {
        on_data_change = {
            on = function(self, callback)
                self.callback = callback
            end
        },
        on_error = {
            on = function(self, callback)
                self.error_callback = callback
            end
        },
        start = function() end
    }
    
    c_network_adapter.ncsi_config_obj = {
        ChipTemp = function() return scheduler_mock end
    }
    c_network_adapter.package_id = 0
    
    -- 打桩外部依赖
    local original_table_insert = table.insert
    table.insert = function() end
    
    -- 执行函数
    c_network_adapter:update_chip_temp_by_ncsi()
    
    -- 模拟NCSI数据变化（恢复正常）
    local temp_value = 50
    scheduler_mock.on_data_change.callback(temp_value)
    
    -- 验证结果：不应该重复调用pause，因为任务已经暂停
    lu.assertEquals(pause_call_count, 0)
    lu.assertEquals(c_network_adapter.TemperatureCelsius, temp_value)
    lu.assertEquals(c_network_adapter.TemperatureStatus, 0)
    lu.assertTrue(c_network_adapter.get_properties_res.ChipTempFromNcsi)
    
    -- 还原打桩
    table.insert = original_table_insert
    
    -- 还原全局状态
    c_network_adapter.smbios_status = original_smbios_status
    c_network_adapter.get_properties_res = original_get_properties_res
    c_network_adapter.ncsi_schedulers = original_ncsi_schedulers
    c_network_adapter.smbus_schedulers = original_smbus_schedulers
    c_network_adapter.ncsi_config_obj = original_ncsi_config_obj
    c_network_adapter.package_id = original_package_id
end

-- 测试当NCSI失败次数未达到阈值时不会启动SMBUS fallback
function TEST_network_adapter:test_ncsi_failed_below_threshold_no_smbus_fallback()
    -- 备份原始状态
    local original_get_properties_res = c_network_adapter.get_properties_res
    local original_ncsi_schedulers = c_network_adapter.ncsi_schedulers
    local original_smbus_schedulers = c_network_adapter.smbus_schedulers
    local original_ncsi_config_obj = c_network_adapter.ncsi_config_obj
    local original_package_id = c_network_adapter.package_id
    
    -- 初始化测试状态
    c_network_adapter.get_properties_res = {ChipTempFromNcsi = true}
    c_network_adapter.ncsi_schedulers = {}
    c_network_adapter.smbus_schedulers = {}
    
    -- 模拟SMBUS任务已暂停
    local resume_call_count = 0
    c_network_adapter.smbus_schedulers.chip_temp_task = {
        is_paused = true,
        resume = function() resume_call_count = resume_call_count + 1 end
    }
    
    -- 模拟NCSI配置对象
    local scheduler_mock = {
        on_data_change = {
            on = function(self, callback)
                self.callback = callback
            end
        },
        on_error = {
            on = function(self, callback)
                self.error_callback = callback
            end
        },
        start = function() end
    }
    
    c_network_adapter.ncsi_config_obj = {
        ChipTemp = function() return scheduler_mock end
    }
    c_network_adapter.package_id = 0
    
    -- 打桩外部依赖
    local original_table_insert = table.insert
    table.insert = function() end
    
    -- 执行函数
    c_network_adapter:update_chip_temp_by_ncsi()
    
    -- 模拟NCSI失败但未达到阈值（只失败2次，阈值是3次）
    for i = 1, 2 do
        scheduler_mock.on_error.error_callback()
    end
    
    -- 验证结果：应该记录错误但不启动fallback
    lu.assertFalse(c_network_adapter.get_properties_res.ChipTempFromNcsi)
    lu.assertEquals(resume_call_count, 0) -- 不应该调用resume
    
    -- 还原打桩
    table.insert = original_table_insert
    
    -- 还原全局状态
    c_network_adapter.get_properties_res = original_get_properties_res
    c_network_adapter.ncsi_schedulers = original_ncsi_schedulers
    c_network_adapter.smbus_schedulers = original_smbus_schedulers
    c_network_adapter.ncsi_config_obj = original_ncsi_config_obj
    c_network_adapter.package_id = original_package_id
end

-- 测试pause后data被正确清空的逻辑
function TEST_network_adapter:test_pause_clears_data_correctly()
    -- 备份原始状态
    local original_smbios_status = c_network_adapter.smbios_status
    local original_get_properties_res = c_network_adapter.get_properties_res
    local original_ncsi_schedulers = c_network_adapter.ncsi_schedulers
    local original_smbus_schedulers = c_network_adapter.smbus_schedulers
    local original_ncsi_config_obj = c_network_adapter.ncsi_config_obj
    local original_package_id = c_network_adapter.package_id
    
    -- 初始化测试状态
    c_network_adapter.smbios_status = 3
    c_network_adapter.get_properties_res = {}
    c_network_adapter.ncsi_schedulers = {}
    c_network_adapter.smbus_schedulers = {}
    
    -- 模拟SMBUS任务正在运行，包含数据
    local original_data = {temp = 25, status = 'active'}
    c_network_adapter.smbus_schedulers.chip_temp_task = {
        is_paused = false,
        pause = function() 
            c_network_adapter.smbus_schedulers.chip_temp_task.is_paused = true 
        end,
        data = original_data
    }
    
    -- 模拟NCSI配置对象
    local scheduler_mock = {
        on_data_change = {
            on = function(self, callback)
                self.callback = callback
            end
        },
        on_error = {
            on = function(self, callback)
                self.error_callback = callback
            end
        },
        start = function() end
    }
    
    c_network_adapter.ncsi_config_obj = {
        ChipTemp = function() return scheduler_mock end
    }
    c_network_adapter.package_id = 0
    
    -- 打桩外部依赖
    local original_table_insert = table.insert
    table.insert = function() end
    
    -- 执行函数
    c_network_adapter:update_chip_temp_by_ncsi()
    
    -- 模拟NCSI数据变化（恢复正常）
    local temp_value = 35
    scheduler_mock.on_data_change.callback(temp_value)
    
    -- 验证任务被暂停
    lu.assertTrue(c_network_adapter.smbus_schedulers.chip_temp_task.is_paused)
    
    -- 验证data被清空
    lu.assertNil(c_network_adapter.smbus_schedulers.chip_temp_task.data)
    
    -- 还原打桩
    table.insert = original_table_insert
    
    -- 还原全局状态
    c_network_adapter.smbios_status = original_smbios_status
    c_network_adapter.get_properties_res = original_get_properties_res
    c_network_adapter.ncsi_schedulers = original_ncsi_schedulers
    c_network_adapter.smbus_schedulers = original_smbus_schedulers
    c_network_adapter.ncsi_config_obj = original_ncsi_config_obj
    c_network_adapter.package_id = original_package_id
end

