-- 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 cjson = require 'cjson'
local signal = require 'mc.signal'
local c_biz_topo = require 'biz_topo.biz_topo'
local bs = require 'mc.bitstring'

TestBizTopo = {}

-- MOCK 访问SMC
local biz_topo_node = {
    mds_obj = {
        RefSmcChip = {
            Read = function (...)
                return '\x31\x01\x30\x30\x30\x30\x30\x30\x30\x31\x30\x34\x30\x33\x30\x32\x30\x32\x33\x39\x34\x30'..
                       '\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00' ..
                       '\x32\x01\x30\x30\x30\x30\x30\x30\x30\x31\x30\x34\x30\x33\x30\x32\x30\x32\x33\x39\x34\x30'..
                       '\x00\x00\x00\x00\x0B\x00\x00\x00\x00\x00'
            end
        },
        position = 1103
    }
}

-- 导入mds对象
local function load_test_sr_data(mds)
    local csr_objs = {}
    local pre_path = './test_data/'
    for i, v0 in ipairs(mds) do
        local file = io.open(pre_path .. v0[1], 'r')
        local mds_data_json = file:read('a')
        local objs = cjson.decode(mds_data_json).Objects
        for k, v in pairs(objs) do
            -- 槽位号和Location根据输入参数改写
            if v.ContainerSlot and v0[2] then
                v.ContainerSlot = v0[2]
            end
            if v.Location and v0[2] then
                v.Location = v.Location .. v0[2]
            end
            if v.RefPCIeAddrInfo then
                v.RefPCIeAddrInfo = v.RefPCIeAddrInfo .. '_' .. i
            end
            local csr_obj = {
                object = v,
                class_name = string.sub(k, 1, string.find(k, '_') - 1),
                position = i
            }
            csr_obj.object.name = k .. '_' .. i -- 对象名重命名
            table.insert(csr_objs, csr_obj)
        end
        file:close()
    end
    return csr_objs
end

-- 测试套间执行前调用
function TestBizTopo:setupClass()
end

-- 测试套件执行后调用
function TestBizTopo:teardownClass()
end

-- sr格式: {{csr文件, 插在哪个槽位上}, ...}
local function biz_topo_new(sr)
    -- 初始化被测单例
    local obj = c_biz_topo.new()
    -- 导入mds数据，mds对象数据描述格式与CSR文件保持一致
    local csr_objs = load_test_sr_data(sr)
    local mock_complete_signal = signal.new()
    -- 模拟对象分发
    for _, v in ipairs(csr_objs) do
        obj:on_add_object(v.class_name, v.object, v.position, mock_complete_signal)
    end
    return obj
end

local function get_pcie_addr_info_by_slot(biz_topo, location, pcie_slot)
    for i, c in ipairs(biz_topo.target_pcie_connectors) do
        if c.ref_pcie_addr_info.mds_obj.Location == location and c.mds_obj.Slot == pcie_slot then
            return c.ref_pcie_addr_info.mds_obj
        end
    end
end

-- 模拟csr加载，检查业务TOPO计算结果
function TestBizTopo:test_construct_biz_topo()
    -- 00000001040302023940
    local sr = {
        {'IEU_00000001040302023940.json', 1},
        {'IEU_00000001040302023940.json', 2},
        {'BCU_00000001020302024339.json', 1},
        {'PSR.json'}
    }
    local biz_topo_obj = biz_topo_new(sr)
    biz_topo_obj:main()
    -- Riser1 PCIeSlot1
    local pcie_addr_info = get_pcie_addr_info_by_slot(biz_topo_obj, 'RiserCard1', 1)
    lu.assertEquals(pcie_addr_info.SlotID, 2)
    lu.assertEquals(pcie_addr_info.SocketID, 0)
    lu.assertEquals(pcie_addr_info.PortID, 0x0C)
    -- Riser1 PCIeSlot2
    pcie_addr_info = get_pcie_addr_info_by_slot(biz_topo_obj, 'RiserCard1', 2)
    lu.assertEquals(pcie_addr_info.SlotID, 3)
    lu.assertEquals(pcie_addr_info.SocketID, 0)
    lu.assertEquals(pcie_addr_info.PortID, 0x08)
    -- Riser2 PCIeSlot1
    pcie_addr_info = get_pcie_addr_info_by_slot(biz_topo_obj, 'RiserCard2', 1)
    lu.assertEquals(pcie_addr_info.SlotID, 5)
    lu.assertEquals(pcie_addr_info.SocketID, 1)
    lu.assertEquals(pcie_addr_info.PortID, 0x04)
    -- Riser2 PCIeSlot2
    pcie_addr_info = get_pcie_addr_info_by_slot(biz_topo_obj, 'RiserCard2', 2)
    lu.assertEquals(pcie_addr_info.SlotID, 6)
    lu.assertEquals(pcie_addr_info.SocketID, 1)
    lu.assertEquals(pcie_addr_info.PortID, 0x00)

    -- 00000001040302023945+00000001040302023947
    sr = {
        -- {板卡数据, 槽位号}
        {'IEU_00000001040302023945.json', 1},
        {'IEU_00000001040302023945.json', 2},
        {'IEU_00000001040302023947.json', 3},
        {'BCU_00000001020302024339.json', 1},
        {'PSR.json'}
    }
    biz_topo_obj = biz_topo_new(sr)
    biz_topo_obj:main()
    -- Riser1 PCIeSlot1
    pcie_addr_info = get_pcie_addr_info_by_slot(biz_topo_obj, 'RiserCard1', 1)
    lu.assertEquals(pcie_addr_info.SlotID, 3)
    lu.assertEquals(pcie_addr_info.SocketID, 0)
    lu.assertEquals(pcie_addr_info.PortID, 0x08)
    -- Riser2 PCIeSlot1
    pcie_addr_info = get_pcie_addr_info_by_slot(biz_topo_obj, 'RiserCard2', 1)
    lu.assertEquals(pcie_addr_info.SlotID, 6)
    lu.assertEquals(pcie_addr_info.SocketID, 1)
    lu.assertEquals(pcie_addr_info.PortID, 0x00)

    -- Riser3 PCIeSlot1
    pcie_addr_info = get_pcie_addr_info_by_slot(biz_topo_obj, 'RiserCard3', 1)
    lu.assertEquals(pcie_addr_info.SlotID, 7)
    lu.assertEquals(pcie_addr_info.SocketID, 1)
    lu.assertEquals(pcie_addr_info.PortID, 0x08)
    pcie_addr_info = get_pcie_addr_info_by_slot(biz_topo_obj, 'RiserCard3', 2)
    lu.assertEquals(pcie_addr_info.SlotID, 8)
    lu.assertEquals(pcie_addr_info.SocketID, 1)
    lu.assertEquals(pcie_addr_info.PortID, 0x0C)
end

function TestBizTopo:test_get_device()
    local src_connector = {
        mds_obj = {
            UpstreamResources = {
                {Name = "SerDes_1_8", ID = 8, Offset = 0, Width = 8},
                {Name = "SerDes_1_7", ID = 7, Offset = 0, Width = 4},
                {Name = "SerDes_1_10", ID = 10, Offset = 0, Width = 4}
            },
            ActualResourceOrder = {"SerDes_1_10", "SerDes_1_7", "SerDes_1_8"},
        },
        res_serdeses = {
            {
                mds_obj = {
                    Name = "SerDes_1_8",
                    ID = 8,
                    LinkWidth = 8,
                    WorkMode = 1,
                    ModeConfigs = {
                        {Mode = 1, Device = {8, 8, 9, 9, 10, 10, 11, 11}, ControllerIndex = {1, 1, 1, 1, 1, 1, 1, 1}},
                    }
                }
            },
            {
                mds_obj = {
                    Name = "SerDes_1_7",
                    ID = 7,
                    LinkWidth = 4,
                    WorkMode = 1,
                    ModeConfigs = {
                        {Mode = 1, Device = {12, 12, 13, 13}, ControllerIndex = {1, 1, 1, 1}},
                    }
                }
            },
            {
                mds_obj = {
                    Name = "SerDes_1_10",
                    ID = 10,
                    LinkWidth = 4,
                    WorkMode = 1,
                    ModeConfigs = {
                        {Mode = 1, Device = {14, 14, 15, 15}, ControllerIndex = {1, 1, 1, 1}}
                    }
                }
            }
        }
    }

    local device = c_biz_topo.get_device(src_connector, 0, 8, 0)
    lu.assertEquals(device, 0x0C)
    device = c_biz_topo.get_device(src_connector, 8, 8, 0)
    lu.assertEquals(device, 0x08)
end

-- BCU x16分2个x8 SerDes，到SEU是4个4x  示例类：BusinessConnector_CPU2UBCDD2 B4c
function TestBizTopo:test_get_device_offset_B4c()
    local src_connector = {
        mds_obj = {
            UpstreamResources = {
                {Name = "SerDes_1_5_A", ID = 5, Offset = 0, Width = 8},
                {Name = "SerDes_1_6_A", ID = 6, Offset = 0, Width = 8}
            }
        },
        res_serdeses = {
            {
                mds_obj = {
                    Name = "SerDes_1_5_A",
                    ID = 0,
                    SocketID = 1,
                    LinkWidth = 8,
                    WorkMode = 1,
                    ModeConfigs = {
                        {
                            Mode = 1,
                            Device = {12, 12, 13, 13, 14, 14, 15, 15},
                            ControllerIndex = {2, 2, 2, 2, 2, 2, 2, 2}
                        },
                    }
                }
            },
            {
                mds_obj = {
                    Name = "SerDes_1_6_A",
                    ID = 1,
                    SocketID= 1,
                    LinkWidth = 8,
                    WorkMode = 1,
                    ModeConfigs = {
                        {
                            Mode = 1,
                            Device = {
                                16, 16, 17, 17, 18, 18, 19, 19
                            },
                            ControllerIndex = {
                                2, 2, 2, 2, 2, 2, 2, 2
                            }
                        },
                    }
                }
            }
        }
    }

    local device = c_biz_topo.get_device(src_connector, 8, 4, 4)
    lu.assertEquals(device, 18)
end

-- BCU x16分2个x8 SerDes，到SEU是4个4x
function TestBizTopo:test_get_device_offset_A1a_A1c()
    local src_connector = {
        mds_obj = {
            UpstreamResources = {
                {Name = "SerDes_0_5_A", ID = 5, Offset = 0, Width = 8},
                {Name = "SerDes_0_6_A", ID = 6, Offset = 0, Width = 8}
            },
            ActualResourceOrder = {"SerDes_0_6_A", "SerDes_0_5_A"},
        },
        res_serdeses = {
            {
                mds_obj = {
                    Name = "SerDes_0_5_A",
                    ID = 0,
                    SocketID = 0,
                    LinkWidth = 8,
                    WorkMode = 1,
                    ModeConfigs = {
                        {
                            Mode = 1,
                            Device = {12, 12, 13, 13, 14, 14, 15, 15},
                            ControllerIndex = {2, 2, 2, 2, 2, 2, 2, 2}
                        },
                    }
                }
            },
            {
                mds_obj = {
                    Name = "SerDes_0_6_A",
                    ID = 1,
                    SocketID = 0,
                    LinkWidth = 8,
                    WorkMode = 1,
                    ModeConfigs = {
                        {
                            Mode = 1,
                            Device = {16, 16, 17, 17, 18, 18, 19, 19},
                            ControllerIndex = {2, 2, 2, 2, 2, 2, 2, 2}
                        },
                    }
                }
            }
        }
    }

    -- Offset为0，A1a场景
    local device = c_biz_topo.get_device(src_connector, 0, 4, 4)
    lu.assertEquals(device, 16)

    -- Offset为8，A1c场景
    local device = c_biz_topo.get_device(src_connector, 8, 4, 4)
    lu.assertEquals(device, 12)
end

-- x8 riser插A1a
function TestBizTopo:test_get_device_offset_riser_riser_to_A1a_A1c()
    -- 默认顺序为A1a/A1c
    local src_connector = {
        mds_obj = {
            UpstreamResources = {
                {Name = "SerDes_0_5_A", ID = 5, Offset = 0, Width = 8},
                {Name = "SerDes_0_6_A", ID = 6, Offset = 0, Width = 8}
            },
            ActualResourceOrder = {"SerDes_0_6_A", "SerDes_0_5_A"},
        },
        res_serdeses = {
            {
                mds_obj = {
                    Name = "SerDes_0_5_A",
                    ID = 0,
                    SocketID = 0,
                    LinkWidth = 8,
                    WorkMode = 1,
                    ModeConfigs = {
                        {
                            Mode = 1,
                            Device = {12, 12, 13, 13, 14, 14, 15, 15},
                            ControllerIndex = {2, 2, 2, 2, 2, 2, 2, 2}
                        },
                    }
                }
            },
            {
                mds_obj = {
                    Name = "SerDes_0_6_A",
                    ID = 1,
                    SocketID = 0,
                    LinkWidth = 8,
                    WorkMode = 1,
                    ModeConfigs = {
                        {
                            Mode = 1,
                            Device = {16, 16, 17, 17, 18, 18, 19, 19},
                            ControllerIndex = {2, 2, 2, 2, 2, 2, 2, 2}
                        },
                    }
                }
            }
        }
    }

    -- link_width=8，port_offset=0,riser卡插A1a场景
    local device = c_biz_topo.get_device(src_connector, 0, 8, 0)
    lu.assertEquals(device, 16)

    -- link_width=16，port_offset=0,riser卡插A1a A1c场景
    local device = c_biz_topo.get_device(src_connector, 0, 16, 0)
    lu.assertEquals(device, 12)

end


-- x8分2个x4 SerDes  示例类：BusinessConnector_CPU2UBC1
function TestBizTopo:test_get_device_offset_1()
    local src_connector = {
        mds_obj = {
            UpstreamResources = {
                {Name = "SerDes_1_0_A", ID = 0, Offset = 0, Width = 4},
                {Name = "SerDes_1_1_A", ID = 1, Offset = 0, Width = 4}
            }
        },
        res_serdeses = {
            {
                mds_obj = {
                    Name = "SerDes_1_0_A",
                    ID = 0,
                    SocketID = 1,
                    LinkWidth = 4,
                    WorkMode = 1,
                    ModeConfigs = {
                        {Mode = 1, Device = {0, 0, 1, 1}, ControllerIndex = {0, 0, 0, 0}},
                    }
                }
            },
            {
                mds_obj = {
                    Name = "SerDes_1_1_A",
                    ID = 1,
                    LinkWidth = 4,
                    WorkMode = 1,
                    ModeConfigs = {
                        {Mode = 1, Device = {2, 2, 3, 3}, ControllerIndex = {0, 0, 0, 0}},
                    }
                }
            }
        }
    }

    local device = c_biz_topo.get_device(src_connector, 0, 4, 4)
    lu.assertEquals(device, 2)
end

-- x8分2个x4 SerDes 与test_get_device_offset_1类似
function TestBizTopo:test_get_device_offset_2()
    local src_connector = {
        mds_obj = {
            UpstreamResources = {
                {Name = "SerDes_0_0_B", ID = 0, Offset = 0, Width = 4},
                {Name = "SerDes_0_1_B", ID = 1, Offset = 0, Width = 4}
            }
        },
        res_serdeses = {
            {
                mds_obj = {
                    Name = "SerDes_0_0_B",
                    ID = 7,
                    SocketID = 0,
                    LinkWidth = 4,
                    WorkMode = 1,
                    ModeConfigs = {
                        {Mode = 1, Device = {20, 20, 21, 21}, ControllerIndex = {3, 3, 3, 3}},
                    }
                }
            },
            {
                mds_obj = {
                    Name = "SerDes_0_1_B",
                    ID = 8,
                    SocketID = 0,
                    LinkWidth = 4,
                    WorkMode = 1,
                    ModeConfigs = {
                        {Mode = 1, Device = {22, 22, 23, 23}, ControllerIndex = {3, 3, 3, 3}},
                    }
                }
            }
        }
    }

    local device = c_biz_topo.get_device(src_connector, 0, 4, 4)
    lu.assertEquals(device, 22)
end

-- x8分1个x8 SerDes  示例类：BusinessConnector_CPU1UBC4
function TestBizTopo:test_get_device_offset_3()
    local src_connector = {
        mds_obj = {
            UpstreamResources = {
                {Name = "SerDes_0_5_B", ID = 5, Offset = 0, Width = 8}
            }
        },
        res_serdeses = {
            {
                mds_obj = {
                    Name = "SerDes_0_5_B",
                    ID = 12,
                    SocketID = 0,
                    LinkWidth = 8,
                    WorkMode = 1,
                    ModeConfigs = {
                        {Mode = 1, Device = {
                            32,
                            32,
                            33,
                            33,
                            34,
                            34,
                            35,
                            35},
                            ControllerIndex = {
                            5,
                            5,
                            5,
                            5,
                            5,
                            5,
                            5,
                            5}},
                    }
                }
            }
        }
    }

    local device = c_biz_topo.get_device(src_connector, 0, 4, 4)
    lu.assertEquals(device, 34)
end


function TestBizTopo:test_parse_link_width()
    local port_cnt, link_width
    -- 多个端口 2X8
    port_cnt, link_width = c_biz_topo.parse_link_width('2X8')
    lu.assertEquals(port_cnt, 2)
    lu.assertEquals(link_width, 8)
    -- 一个端口 X16
    port_cnt, link_width = c_biz_topo.parse_link_width('X16')
    lu.assertEquals(port_cnt, 1)
    lu.assertEquals(link_width, 16)
end

function TestBizTopo:test_get_matched_unit_config_static()
    local unit_config_list = {
        {
            mds_obj = {
                SlotType = 'IEU',
                SlotNumber = 1,
                Configurations = {
                    {
                        UID = '00000001040302044498',
                        Index = 2,
                        SrcPortName = {
                            "A1a",
                            "A2a",
                            "A2c"
                        },
                        TargetPortID = {
                            17,
                            33,
                            49
                        },
                        Slot = {
                            1,
                            2,
                            3
                        }
                    }
                }
            }
        }
    }
    local unit_config = c_biz_topo:get_matched_unit_config(unit_config_list, 'IEU', 1, '00000001040302044498')
    lu.assertNotIsNil(unit_config)

    unit_config = c_biz_topo:get_matched_unit_config(unit_config_list, 'IEU', 2, '00000001040302044498')
    lu.assertIsNil(unit_config)
end

local dynamic_unit_config_list = {
    {
        mds_obj = {
            SlotType = 'SEU',
            SlotNumber = 1,
            Configurations = {
                {
                    UID = '00000001030302024340',
                    Index = 0,
                    Default = true,
                    SrcPortName = {
                        "D7a",
                        "D6a"
                    },
                    TargetPortID = {
                        17,
                        49
                    },
                    Slot = {
                        44,
                        45,
                        46,
                        47
                    }
                }
            }
        }
    },
    {
        mds_obj = {
            SlotType = 'SEU',
            SlotNumber = 1,
            Configurations = {
                {
                    UID = '00000001030302024340',
                    Index = 0,
                    SrcPortName = {
                        "D4a",
                        "D5a"
                    },
                    TargetPortID = {
                        33,
                        49
                    },
                    Slot = {
                        44,
                        45,
                        46,
                        47
                    }
                }
            }
        }
    },
}

function TestBizTopo:test_get_matched_unit_config_dynamic()
    local sr = {
        {'SEU_00000001030302024340.json', 1},
        {'BCU_00000001020302024339.json', 1},
        {'PSR.json'}
    }
    local biz_topo_obj = biz_topo_new(sr)
    biz_topo_obj:main()

    table.insert(biz_topo_obj.biz_topo_node_list, biz_topo_node)
    -- 做动态建链的UID
    local unit_config = biz_topo_obj:get_matched_unit_config(dynamic_unit_config_list, 'SEU', 1, '00000001030302024340')
    lu.assertNotIsNil(unit_config)

    unit_config = biz_topo_obj:get_matched_unit_config(dynamic_unit_config_list, 'SEU', 2, '00000001030302024340')
    lu.assertIsNil(unit_config)
end

function TestBizTopo:test_find()
    -- 基本数据类型
    local index = c_biz_topo.find({4, 5, 6}, 6)
    lu.assertEquals(index, 3)

    -- table类型
    local obj_coll = {{name = 'A', id = 1}, {name = 'B', id = 2}}
    local obj = c_biz_topo.find(obj_coll, function (item)
        if item.name == 'B' then
            return true
        end
    end)
    lu.assertEquals(obj.id, 2)
end

function TestBizTopo:test_parse_port_name()
    local zone, port_id = c_biz_topo.parse_port_name('A2a')
    lu.assertEquals(zone, 1)
    lu.assertEquals(port_id, 5)
    local zone, port_id = c_biz_topo.parse_port_name('B5a')
    lu.assertEquals(zone, 2)
    lu.assertEquals(port_id, 17)
end

-- 功能: 多种pcie卡插法配置，找到最匹配的插法
local seu_unit_config_list = {
    {
        mds_obj = {
            SlotType = 'SEU',
            SlotNumber = 5,
            Configurations = {
                {
                    UID = '00000001030302024340',
                    Index = 0,
                    Default = true,
                    SrcPortName = {
                        "D7a",
                        "D6a"
                    },
                    TargetPortID = {
                        17,
                        49
                    },
                    Slot = {
                        44,
                        45,
                        46,
                        47
                    }
                },
                {
                    UID = '00000001030302046571',
                    Index = 0,
                    SrcPortName = {
                        "D4a",
                        "D5a"
                    },
                    TargetPortID = {
                        33,
                        17
                    },
                    Slot = {
                        46,
                        47
                    }
                },
                {
                    UID = '00000001030302024340',
                    Index = 0,
                    SrcPortName = {
                        "D4a",
                        "D5a"
                    },
                    TargetPortID = {
                        33,
                        49
                    },
                    Slot = {
                        44,
                        45,
                        46,
                        47
                    }
                },
                {
                    UID = '00000001030302024340',
                    Index = 0,
                    SrcPortName = {
                        "A4a"
                    },
                    TargetPortID = {
                        1
                    },
                    Slot = {
                        44,
                        45,
                        46,
                        47
                    }
                },
                {
                    UID = '00000001030302046571',
                    Index = 0,
                    Default = true,
                    SrcPortName = {
                        "D5a"
                    },
                    TargetPortID = {
                        17
                    },
                    Slot = {
                        46,
                        47
                    }
                }
            }
        }
    }
}

-- 用例场景: UnitConfiguration没有TargetPortID
-- 预期结果: 无法匹配，获取默认插法配置
local seu_unit_config_list_no_target_port_id = {
    {
        mds_obj = {
            SlotType = 'SEU',
            SlotNumber = 5,
            Configurations = {
                {
                    UID = '00000001030302024340',
                    Index = 0,
                    Default = true,
                    SrcPortName = {
                        "D7a",
                        "D6a"
                    },
                    TargetPortID = {
                    },
                    Slot = {
                        44,
                        45,
                        46,
                        47
                    }
                },
                {
                    UID = '00000001030302024340',
                    Index = 0,
                    SrcPortName = {
                        "D4a",
                        "D5a"
                    },
                    TargetPortID = {
                    },
                    Slot = {
                        44,
                        45,
                        46,
                        47
                    }
                },
                {
                    UID = '00000001030302024340',
                    Index = 0,
                    SrcPortName = {
                        "A4a"
                    },
                    TargetPortID = {
                    },
                    Slot = {
                        44,
                        45,
                        46,
                        47
                    }
                },
            }
        }
    }
}
function TestBizTopo:test_match_unit_config_with_topo_no_target_port_id()
    local sr = {
        {'SEU_00000001030302024340.json', 1},
        {'BCU_00000001020302024339.json', 1},
        {'PSR.json'}
    }
    local biz_topo_obj = biz_topo_new(sr)
    biz_topo_obj:main()

    table.insert(biz_topo_obj.biz_topo_node_list, biz_topo_node)

    -- 预期结果: 无法匹配，获取默认插法配置
    local unit_config = biz_topo_obj:get_matched_unit_config(seu_unit_config_list_no_target_port_id,
        'SEU', 5, '00000001030302024340')
    lu.assertNotIsNil(unit_config)
    lu.assertEquals(unit_config.Default, true)
end

-- 用例场景: UnitConfiguration没有SrcPortName
-- 预期结果: 无法匹配，获取默认插法配置
local seu_unit_config_list_no_src_port_name = {
    {
        mds_obj = {
            SlotType = 'SEU',
            SlotNumber = 5,
            Configurations = {
                {
                    UID = '00000001030302024340',
                    Index = 0,
                    Default = true,
                    SrcPortName = {
                    },
                    TargetPortID = {
                        17,
                        49
                    },
                    Slot = {
                        44,
                        45,
                        46,
                        47
                    }
                },
                {
                    UID = '00000001030302024340',
                    Index = 0,
                    SrcPortName = {
                    },
                    TargetPortID = {
                        33,
                        49
                    },
                    Slot = {
                        44,
                        45,
                        46,
                        47
                    }
                },
                {
                    UID = '00000001030302024340',
                    Index = 0,
                    SrcPortName = {
                    },
                    TargetPortID = {
                        1
                    },
                    Slot = {
                        44,
                        45,
                        46,
                        47
                    }
                },
            }
        }
    }
}
function TestBizTopo:test_match_unit_config_with_topo_no_src_port_name()
    local sr = {
        {'SEU_00000001030302024340.json', 1},
        {'BCU_00000001020302024339.json', 1},
        {'PSR.json'}
    }
    local biz_topo_obj = biz_topo_new(sr)
    biz_topo_obj:main()

    table.insert(biz_topo_obj.biz_topo_node_list, biz_topo_node)

    local unit_config = biz_topo_obj:get_matched_unit_config(seu_unit_config_list_no_src_port_name,
        'SEU', 5, '00000001030302024340')
    lu.assertNotIsNil(unit_config)
    lu.assertEquals(unit_config.Default, true)
end


local bs_topo = bs.new([[<<
    target_port_id:8,
    index:8,
    uid:24/string,
    port_id:8,
    _:5/string
>>]])

local function create_biz_topo_node(test_data, slot)
    local data = ''
    for _, d in pairs(test_data) do
        data = data .. bs_topo:pack(d)
    end
    return {
        mds_obj = {
            Slot = slot,
            RefSmcChip = {
                Read = function(...)
                    return data
                end
            }
        }
    }
end

-- 用例场景: cpld读取的拓扑信息为空
-- 预期结果: 无法匹配，获取默认插法配置
function TestBizTopo:test_match_unit_config_with_topo_no_cpld_info()
    local sr = {
        {'SEU_00000001030302024340.json', 1},
        {'BCU_00000001020302024339.json', 1},
        {'PSR.json'}
    }
    local biz_topo_obj = biz_topo_new(sr)
    biz_topo_obj:main()

    local biz_topo_node_data = {}

    -- 模拟bcu smc命令
    local biz_topo_node = create_biz_topo_node(biz_topo_node_data)
    table.insert(biz_topo_obj.biz_topo_node_list, biz_topo_node)

    local unit_config = biz_topo_obj:get_matched_unit_config(seu_unit_config_list, 'SEU', 5, '00000001030302024340')
    lu.assertNotIsNil(unit_config)
    lu.assertEquals(unit_config.Default, true)
end

-- 用例场景: cpld读取的uid与UnitConfiguration的uid不匹配
-- 预期结果: 无法匹配，获取默认插法配置
function TestBizTopo:test_match_unit_config_with_topo_uid_not_match_cpld_info()
    local sr = {
        {'SEU_00000001030302024340.json', 1},
        {'BCU_00000001020302024339.json', 1},
        {'PSR.json'}
    }
    local biz_topo_obj = biz_topo_new(sr)
    biz_topo_obj:main()

    local biz_topo_node_data = {
        {target_port_id = 33, index = 0, uid = '00000001030302046571', port_id = 9},
        {target_port_id = 17, index = 0, uid = '00000001030302046571', port_id = 12}
    }

    -- 模拟bcu smc命令
    local biz_topo_node = create_biz_topo_node(biz_topo_node_data)
    table.insert(biz_topo_obj.biz_topo_node_list, biz_topo_node)

    local unit_config = biz_topo_obj:get_matched_unit_config(seu_unit_config_list, 'SEU', 5, '00000001030302024340')
    lu.assertNotIsNil(unit_config)
    lu.assertEquals(unit_config.Default, true)
end

-- 用例场景: cpld读取的拓扑信息与UnitConfiguration部分配置一致
-- 预期结果: 无法匹配，获取默认插法配置
function TestBizTopo:test_match_unit_config_with_topo_uid_part_match_cpld_info()
    local sr = {
        {'SEU_00000001030302024340.json', 1},
        {'BCU_00000001020302024339.json', 1},
        {'PSR.json'}
    }
    local biz_topo_obj = biz_topo_new(sr)
    biz_topo_obj:main()

    local biz_topo_node_data = {
        {target_port_id = 17, index = 0, uid = '00000001030302024340', port_id = 12}
    }

    -- 模拟bcu smc命令
    local biz_topo_node = create_biz_topo_node(biz_topo_node_data)
    table.insert(biz_topo_obj.biz_topo_node_list, biz_topo_node)

    local unit_config = biz_topo_obj:get_matched_unit_config(seu_unit_config_list, 'SEU', 5, '00000001030302024340')
    lu.assertNotIsNil(unit_config)
    lu.assertEquals(unit_config.Default, true)
end

function printTable(t, indent)
    indent = indent or ""
    for k, v in pairs(t) do
        if type(v) == "table" then
            print(indent .. tostring(k) .. ":")
            printTable(v, indent .. "  ")
        else
            print(indent .. tostring(k) .. " = " .. tostring(v))
        end
    end
end

-- 用例场景: cpld读取的portId与UnitConfiguration的portId不匹配
-- 预期结果: 插法错误，target_port_id不一致，选默认的插法配置
function TestBizTopo:test_match_unit_config_with_topo_port_id_mismatch_cpld_info()
    local sr = {
        {'SEU_00000001030302024340.json', 1},
        {'BCU_00000001020302024339.json', 1},
        {'PSR.json'}
    }
    local biz_topo_obj = biz_topo_new(sr)
    biz_topo_obj:main()

    local biz_topo_node_data = {
        {target_port_id = 33, index = 0, uid = '00000001030302024340', port_id = 13},
        {target_port_id = 49, index = 0, uid = '00000001030302024340', port_id = 17}
    }

    -- 模拟bcu smc命令
    local biz_topo_node_test = create_biz_topo_node(biz_topo_node_data)
    table.insert(biz_topo_obj.biz_topo_node_list, biz_topo_node_test)

    biz_topo_obj.topo_info = {
        ['D'] = {
            [13] = {
                target_port_id = 33,
                index = 0,
                uid = '00000001030302024340',
                port_id = 13,
            },
            [17] = {
                target_port_id = 1, -- 预期是49
                index = 0,
                uid = '00000001030302024340',
                port_id = 17,
            }
        }
    }

    local unit_config = biz_topo_obj:get_matched_unit_config(seu_unit_config_list, 'SEU', 5, '00000001030302024340')
    
    lu.assertNotIsNil(unit_config)
    lu.assertEquals(unit_config.Default, true)
end

-- 用例场景: cpld读取的portId与UnitConfiguration的portId不匹配
-- 预期结果: 插法不全，获取最接近的插法配置
function TestBizTopo:test_match_unit_config_with_topo_incomplete_cpld_info()
    local sr = {
        {'SEU_00000001030302024340.json', 1},
        {'BCU_00000001020302024339.json', 1},
        {'PSR.json'}
    }
    local biz_topo_obj = biz_topo_new(sr)
    biz_topo_obj:main()

    local biz_topo_node_data = {
        {target_port_id = 33, index = 0, uid = '00000001030302024340', port_id = 13},
        {target_port_id = 49, index = 0, uid = '00000001030302024340', port_id = 17}
    }

    -- 模拟bcu smc命令
    local biz_topo_node_test = create_biz_topo_node(biz_topo_node_data)
    table.insert(biz_topo_obj.biz_topo_node_list, biz_topo_node_test)

    biz_topo_obj.topo_info = {
        ['D'] = {
            [13] = {
                target_port_id = 33,
                index = 0,
                uid = '00000001030302024340',
                port_id = 13,
            },
        }
    }

    local unit_config = biz_topo_obj:get_matched_unit_config(seu_unit_config_list, 'SEU', 5, '00000001030302024340')

    lu.assertNotIsNil(unit_config)
    lu.assertIsNil(unit_config.Default)
    lu.assertEquals(unit_config.SrcPortName[1], "D4a")
    lu.assertEquals(unit_config.SrcPortName[2], "D5a")
    lu.assertEquals(unit_config.UID, '00000001030302024340')
    lu.assertEquals(unit_config.matched_times, 1)
    lu.assertEquals(unit_config.port_num, 2)
    lu.assertEquals(unit_config.status, 5)
end