Prhub

#26908 [CI][PD] Add unit tests for nixl backend

原始 PR 作者 nbarzilie 合并时间 2026-06-10 14:31 文件变更 1 提交数 5 评论 8 代码增减 +776 / -0

执行摘要

为 NIXL 分解控制逻辑添加 CPU 单元测试

NIXL 分解控制路径缺少单元测试,这些测试用于保护 NIXL 协议解析、传输完成状态、通知处理、接收端轮询、节点故障清理和暂存缓冲区传输设置等逻辑,无需真实 NIXL 运行时、GPU 或 RDMA 设备,也无需启动服务器。

此 PR 值得相关开发者精读,特别是其 FakeAgent 设计和 Mock 策略,可作为同类组件单元测试的参考模板。对于不影响分解模块的团队成员仅需了解已添加覆盖即可。

讨论亮点
  1. Mock 路径选择:gemini-code-assist 建议直接 patch time.time 而非 sglang.srt.disaggregation.nixl.conn.time.time,以增强重构鲁棒性。作者回应标准做法是 patch 代码查找的名称,等待维护者意见。最终维护者未明确要求修改。
  2. 文件合并建议:维护者 ShangmingCai 建议将多个测试文件合并为一个 test_nixl_backend_basic.py 以简化触发。作者采纳并合并。

实现拆解

  1. 创建测试文件:在 test/registered/unit/disaggregation/ 下新建 test_nixl_backend_basic.py,导入 NIXL 相关生产代码和测试工具。
  2. 实现 Fake Agent:定义 NotificationFakeAgentStagingFakeAgent 类,模拟 NIXL 代理的通知获取、内存注册、传输描述获取、初始化及传输行为,使测试不依赖真实后端。
  3. 编写辅助 Fake 类:提供 FakeQueueFakeTensorFakeStagingBufferFakeStagingAllocator_fake_staging_buffer_module 函数,用于模拟暂存缓冲区和内存分配。
  4. 编写六个测试类:分别测试 TransferInfo.from_zmqTransferStatus、通知解析、接收端轮询、节点故障处理和暂存缓冲区逻辑,每个类包含多个用例验证边界条件和异常路径。
  5. 注册到 CPU CI:使用 register_cpu_ci(est_time=23, suite="base-a-test-cpu") 将测试注册到 CPU 持续集成套件。
文件 模块 状态 重要度
test/registered/unit/disaggregation/test_nixl_backend_basic.py NIXL 测试 added 7.49

关键符号

NotificationFakeAgent.__init__ NotificationFakeAgent.get_new_notifs StagingFakeAgent.__init__ StagingFakeAgent.register_memory StagingFakeAgent.get_xfer_descs StagingFakeAgent.initialize_xfer StagingFakeAgent.transfer

关键源码片段

test/registered/unit/disaggregation/test_nixl_backend_basic.py test-coverage

唯一变更文件,包含 6 个测试类共 776 行,覆盖 NIXL 分解控制路径的所有核心组件。

"""Basic CPU unit tests for NIXL disaggregation control paths."""# 导入生产模块和测试工具
from sglang.srt.disaggregation.nixl.conn import (
    KVArgsRegisterInfo, NixlKVManager, NixlKVReceiver,
    NixlKVSender, TransferInfo, TransferKVChunk, TransferStatus,
)
from sglang.test.ci.ci_register import register_cpu_ciregister_cpu_ci(est_time=23, suite="base-a-test-cpu")# 模拟 Notification 代理:返回预设消息
class NotificationFakeAgent:
    def __init__(self, messages):
        self.messages = messages
​
    def get_new_notifs(self):
        return {"peer": [msg.encode("ascii") for msg in self.messages]}# 模拟 Staging 代理:记录调用并返回固定值
class StagingFakeAgent:
    def __init__(self, register_result=None):
        self.register_result = register_result if register_result is not None else ["desc"]
        self.calls = [] # 记录所有调用
​
    def register_memory(self, addrs, mem_type):
        self.calls.append(("register_memory", addrs, mem_type))
        return self.register_result
​
    def get_xfer_descs(self, reqs, mem_type):
        self.calls.append(("get_xfer_descs", reqs, mem_type))
        return f"{mem_type}_{len(self.calls)}"
​
    def initialize_xfer(self, *args):
        self.calls.append(("initialize_xfer", args))
        return "handle"
​
    def transfer(self, handle):
        self.calls.append(("transfer", handle))
        return "DONE"# 测试 TransferInfo.from_zmq 解析
class TestNixlTransferInfo(CustomTestCase):
    def test_from_zmq_parses_required_fields(self):
        # 构造 ZMQ 消息(二进制包)
        msg = [b"7", b"127.0.0.1", b"12345", b"decode_agent",
               np.array([3,5,8], dtype=np.int32).tobytes(),
               b"4", b"2", pack_int_lists([[1,2],[],[9]], "i"), b"11"]
        info = TransferInfo.from_zmq(msg)
        self.assertEqual(info.room, 7)
        self.assertEqual(info.endpoint, "127.0.0.1")
        np.testing.assert_array_equal(info.dst_kv_indices, [3,5,8])
        self.assertEqual(info.dst_aux_index, 4)
        self.assertEqual(info.dst_state_indices, [[1,2],[],[9]])
        self.assertEqual(info.decode_prefix_len, 11)

评论区精华

Mock time.time 的建议 正确性

gemini-code-assist 建议直接 patch 全局 time.time 而非 sglang.srt.disaggregation.nixl.conn.time.time,认为后者在重构时容易失效。作者回应标准做法是 patch 被测试代码实际引用的名称,等待维护者意见。

结论:维护者未明确要求修改,PR 合并时未变更该 mock 策略。 · unresolved

合并测试文件以简化触发 测试

维护者 ShangmingCai 建议将多个测试文件合并为一个 test_nixl_backend_basic.py,以便通过 /rerun-test 命令一次性运行。

结论:作者采纳建议,将六个测试文件合并为一个。 · 已解决

风险与影响

本 PR 仅添加测试代码,不修改任何生产代码,无回归风险。测试全部在 CPU 上运行,无需 GPU 或 RDMA,无性能影响。Mock 模拟的可靠性取决于与真实后端行为的对齐程度,但测试设计已覆盖主要控制路径。

对用户无直接影响。对系统,新增的 CPU 单元测试在每次 CI 中自动运行,提高 NIXL 分解模块变更的质量保障。对团队,便于在开发环境中快速验证 NIXL 控制逻辑,减少对完整环境的依赖。影响范围仅限于测试基础设施和分解模块的开发者。

无风险,纯测试变更

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论