Rocket.Chat Matrix Federation 集成测试全指南:federation-matrix 包的本地端到端测试环境搭建
导读
federation-matrix 是 Rocket.Chat 官方 Enterprise(EE)侧提供的 Matrix 联邦(Federation)集成包,用于实现 Rocket.Chat 与 Matrix 生态之间的跨平台互通。本文以仓库中的 federation-matrix README 为主体,结合 docker-compose.test.yml、集成测试运行脚本 与端到端测试源码,完整讲解该包集成测试环境如何一键搭建:从本地编译 Rocket.Chat、拉起 Synapse/Element/MongoDB 集群,到运行覆盖私聊、房间、权限、封禁等场景的 E2E 用例。读完你将掌握 yarn test:integration 的全部命令参数、各容器的角色分工,以及如何用 --keep-running/--no-test 保留服务进行手动联调与二次验证。
federation-matrix:跨平台联邦通信的集成层
@rocket.chat/federation-matrix 是 Rocket.Chat 官方仓库中的私有包(见 package.json,版本 0.2.0),其 README 开宗明义地将其定位为 "Rocket.Chat's Matrix federation integration package for cross-platform communication",即 Rocket.Chat 的 Matrix 联邦集成包。
从源码结构可以确认其职责边界:
- FederationMatrix.ts 是核心服务类,继承
ServiceClass并实现IFederationMatrixService,服务名为federation-matrix。它订阅Federation_Service_Domain、Federation_Service_EDU_Process_Typing(typing 事件)、Federation_Service_EDU_Process_Presence(在线状态)等 Rocket.Chat 运行时设置,把它们实时映射为内部状态; src/helpers/message.parsers提供了toExternalMessageFormat/toInternalMessageFormat/toExternalQuoteMessageFormat/toInternalQuoteMessageFormat等消息双向格式转换器;- 内置媒体类型映射(见 FederationMatrix.ts):
image→m.image、video→m.video、audio→m.audio、file→m.file; - 依赖项中包括
@rocket.chat/federation-sdk、@rocket.chat/core-services、@rocket.chat/models、@rocket.chat/network-broker等核心工作区包,以及matrix-js-sdk(测试用)。
要验证这样一套"本地 Rocket.Chat + 远端 Matrix Homeserver"的联邦能力,仅靠单元测试远远不够,因此该包提供了开箱即用的容器化集成测试方案,这正是 README 的主体内容。
集成测试的整体工作方式
README 的 "How It Works" 一节概括了整套机制,对照 run-integration-tests.sh 可还原出完整执行流水线:
- 本地构建 Rocket.Chat(默认模式下):脚本先回到仓库根目录执行
yarn build构建各包,再进入apps/meteor执行meteor build --server-only --directory <临时目录>产出 Meteor bundle。为避免 Meteor 构建过程中的符号链接(symlink)问题,构建目录使用mktemp -d创建在仓库之外的临时位置(见脚本中BUILD_DIR的定义); - 启动联邦服务:通过
docker compose -f docker-compose.test.yml --profile <test|element> up -d拉起 Rocket.Chat(rc1)、Synapse(hs1)、MongoDB(以及可选 Element)四个服务; - 等待服务就绪:脚本用
curl轮询两个就绪探针——https://rc1/api/info(Rocket.Chat)与https://hs1/_matrix/client/versions(Synapse),单次最长等待MAX_WAIT_TIME=240秒、每 5 秒检查一次; - 运行端到端测试:就绪后进入包目录执行
yarn test:federation(即jest --config jest.config.federation.ts),测试结束除非显式指定,否则自动清理全部容器(docker compose ... down -v并删除临时构建目录)。
脚本对失败路径做了兜底:测试失败时先输出 rc1 与 hs1 的容器日志再清理;收到 Ctrl+C(SIGINT)或退出信号时也会先执行清理逻辑(见脚本顶部的 trap cleanup EXIT TERM 与 trap '...INT')。
环境准备:一条不能省略的 hosts 配置
集成测试运行前必须先在宿主机 /etc/hosts 中追加如下三条映射(README 原样给出):
127.0.0.1 element
127.0.0.1 hs1
127.0.0.1 rc1
为什么不能省略?因为测试环境中的服务全部通过 HTTPS 域名互相访问:Rocket.Chat 的 ROOT_URL 被设置为 https://rc1,Synapse 的 server_name 为 hs1,Element 绑定 https://element。同时测试脚本(以及测试代码)会用 curl --resolve rc1:443:127.0.0.1 这类方式把请求解析到本地回环地址,而测试套件(如 ddp-listener.ts)连接服务时依赖这些域名能解析到本机。
还需要注意,访问 https://rc1、https://hs1 时需信任测试环境的本地根证书。证书文件位于 docker-compose/traefik/certs/ca/rootCA.crt,脚本中通过 NODE_EXTRA_CA_CERTS(指向 rootCA)注入 Node 进程,Rocket.Chat 容器则通过挂载 rootCA.pem 到 /usr/local/share/ca-certificates/ 完成信任链配置。
测试栈拆解:docker-compose.test.yml 里的每一环
docker-compose.test.yml 是整个测试环境的地基。它定义了 test 与 element 两个 profile:
testprofile:仅含 Rocket.Chat(rc1)、Synapse(hs1)、MongoDB,外加 Traefik 反向代理;elementprofile:在test基础上追加 Element Web 客户端,用于验证"从 Matrix 官方客户端视角看 Rocket.Chat 联邦房间"是否正常。
各服务角色如下:
| 服务 | 镜像/来源 | 关键配置 | 说明 |
|---|---|---|---|
| traefik | traefik:v3.6.6 |
暴露 80/443/8080,Docker provider,按 Host 路由(Host(\rc1`)、Host(`hs1`)、Host(`element`)`),统一走 TLS |
充当 HTTPS 入口与证书终止代理 |
| hs1 | matrixdotorg/synapse:v1.157.2 |
见 homeserver.yaml | 联邦对端 Homeserver(Synapse) |
| rc1 | 本地 meteor build 产物或 rocketchat/rocket.chat:latest |
ROOT_URL: https://rc1,MONGO_URL 指向 rs0 副本集 |
被测方 Rocket.Chat 实例 |
| mongo | mongo:8.0(可用环境变量覆盖) |
暴露 27017:27017,入口脚本自动 rs.initiate 初始化副本集 rs0 |
Rocket.Chat 依赖的数据库 |
| element | vectorim/element-web |
配置文件 config.json | 可选:Matrix Web 客户端 |
几个值得注意的设计细节:
- 网络隔离:compose 文件定义了
hs1-net、rc1-net、element-net三个隔离网络,Traefik 同时挂到三个网络并在每个网络里以hs1、rc1、rc.host(element 网络还含element)多个别名存在。配置文件中的注释解释了原因:若让同一网络内的"宿主机与容器服务同名",会导致 Home Server 地址解析出错——容器有时会尝试直接访问同名容器而不是走 Traefik,从而拿到既没有 SSL 也不暴露正确端口的错误地址。这是该测试栈刻意模拟真实跨服务器环境的手段。 - Synapse 的用户播种:hs1 的
entrypoint会先等待自身 8008 端口的 client API 就绪,然后连续调用register_new_matrix_user注册 4 个管理员账号:admin/admin、alice/alice、bob/bob、cleiton/cleiton。这些账号正是联邦 E2E 测试中"远端用户"的来源。 - Rocket.Chat 通过环境变量覆盖设置:rc1 服务用
OVERWRITE_SETTING_*系列变量直接注入关键配置,其中联邦能力相关的两行正是测试的前提:OVERWRITE_SETTING_Federation_Service_Enabled: true(开启联邦服务);OVERWRITE_SETTING_Federation_Service_Domain: rc1(声明本实例的联邦域名,对应源码中Federation_Service_Domain设置与@user:rc1形式的 Matrix ID)。 其余还包含ROCKETCHAT_LICENSE(注入 Enterprise 授权)、ADMIN_USERNAME/ADMIN_PASS/ADMIN_EMAIL(初始化管理员)以及OVERWRITE_SETTING_Show_Setup_Wizard: completed(跳过初始化向导)。
- MongoDB 副本集:rc1 的
MONGO_URL是mongodb://mongo:27017/rc1?replicaSet=rs0,因此 mongo 容器启动后会自行完成副本集初始化,这是 Rocket.Chat 正常运行与 Meteor DDP 测试的前提。
Synapse 侧的 homeserver.yaml 则是面向联调的"宽松"配置:enable_registration: true、allow_public_rooms_over_federation: true、federation_verify_certificates: false,并将所有限流阈值调高(消息、登录、入房、联邦等 rc_* 项均为 10000/s 级别),避免测试过程被 Synapse 的速率限制打断。该配置仅供测试使用,不应照搬到生产环境。
完整参数说明与命令示例
集成测试由包的 test:integration 脚本驱动,在 package.json 中定义为执行 ./tests/scripts/run-integration-tests.sh。README 给出了默认与所有 flag 的组合用法。
默认行为
yarn test:integration
不携带任何参数时:本地构建最新代码 → 启动 test profile 的全部服务 → 就绪后运行 E2E 测试 → 结束后自动清理容器与临时构建目录。
可用 Flag 一览(README 原文语义)
| Flag | 作用 | 默认值 |
|---|---|---|
| (无参数) | 本地构建代码并运行测试 | 默认模式 |
--image [IMAGE] |
改用预构建 Docker 镜像,跳过本地 meteor 构建 | 未指定镜像名时默认 rocketchat/rocket.chat:latest |
--keep-running |
测试完成后保留容器运行,供手动验证 | 关闭(自动清理) |
--element |
在测试环境中额外包含 Element Web 客户端 | 关闭 |
--no-test |
只启动容器、跳过测试(适合手动测试或调试) | 关闭 |
补充说明:脚本内部还支持若干未写入 README 的调试类参数,通过
yarn test:integration --help可查看,包括--start-containers-only(等价于--keep-running --no-test)、--ci(CI 模式:保留容器且不回滚测试退出码)、--logs(启动容器后直接打印 rc1/hs1 日志)。它们主要用于流水线与排障,日常使用 README 中的五个 flag 即可。
常用示例
用预构建镜像测试(不本地编译,最快):
yarn test:integration --image
指定特定版本的预构建镜像:
yarn test:integration --image rocketchat/rocket.chat:latest
测试结束后保留服务便于人工查看:
yarn test:integration --keep-running
带上 Element 客户端一起跑(等价于切换到 element profile):
yarn test:integration --element
只起环境不跑测试(手动/调试模式):
yarn test:integration --no-test
手动模式下把 Element 也带上,并且全程保留容器:
yarn test:integration --keep-running --element --no-test
多 flag 组合的完整示例:
yarn test:integration --image rocketchat/rocket.chat:latest --keep-running --element
镜像参数的行为细节:--image 后面若紧跟的是另一个 flag(例如 --image --keep-running)或没有值,则自动回落为 rocketchat/rocket.chat:latest;若希望指定镜像,把镜像名紧跟其后即可。使用预构建镜像时,脚本通过 export ROCKETCHAT_IMAGE=... 覆盖 compose 中 rc1 的 image,而本地构建模式下则通过 ROCKETCHAT_BUILD_CONTEXT 与 ROCKETCHAT_DOCKERFILE(指向 apps/meteor/.docker/Dockerfile.alpine 的 release-standard target)让 compose 现场构建。
测试背后:Jest 配置与 E2E 用例覆盖
容器就绪后,真正执行的是 yarn test:federation,其配置见 jest.config.federation.ts:
- 基于
@rocket.chat/jest-presets/server预设,testMatch限定在tests/end-to-end/**/*.spec.ts; - 单项用例超时 30 秒,开启
forceExit与detectOpenHandles以规避分布式场景下的句柄残留; - 配置了
globalTeardown(见 teardown.ts)用于全局资源回收; - 若设置
QASE_TESTOPS_JEST_API_TOKEN,会自动附加 jest-qase 报告器并把运行结果回传到 Qase TestOps(项目默认RC),便于追溯回归。
端到端用例按联邦能力维度拆分(目录 tests/end-to-end):
| 用例文件 | 覆盖场景 |
|---|---|
dms.spec.ts |
跨服务器私聊(DM):建联、收发消息 |
room.spec.ts |
联邦房间的创建与房间级消息流 |
messaging.spec.ts |
常规消息、消息往返的一致性 |
first-contact.spec.ts |
"首次接触":某用户第一次被对方实例感知时的行为 |
permissions.spec.ts |
跨域用户的权限边界 |
ban.spec.ts |
联邦场景下的封禁与会话隔离 |
测试账户体系沉淀在 tests/helper/config.ts 中,全部支持用环境变量覆盖并带本地开发默认值:
- rc1(Rocket.Chat 侧):管理员
admin/admin,附加用户user2/user2pass,首接触用户user3/user3pass; - hs1(Synapse 侧):管理员
admin/admin,附加用户alice/alice,首接触用户cleiton/cleiton(该用户由 compose 注册且刻意不让其他 spec 使用,以保证 first-contact 语义可复现)。
也就是说,E2E 用例在"rc1 的本地用户 ↔ hs1 的 Matrix 用户"之间构造真实的跨联邦会话,Matrix 侧的账号形如 @alice:hs1,Rocket.Chat 侧则形如 @admin:rc1。
服务地址与手动联调
README 汇总了在 --keep-running 或 --no-test 模式下各服务的访问入口(脚本就绪后也会原样打印):
| 服务 | 地址 | 说明 |
|---|---|---|
| Rocket.Chat | https://rc1 |
被测实例,管理员 admin/admin |
| Synapse | https://hs1 |
联邦对端 Homeserver |
| MongoDB | localhost:27017 |
本地直连端口(rc1 数据,副本集 rs0) |
| Element | https://element |
仅加 --element flag 后可用 |
保留环境后若要停止容器,可在包目录执行(COMPOSE_PROFILE 取决于是否带 --element):
docker compose -f docker-compose.test.yml --profile test down -v
# 若启用了 Element,profile 为 element
docker compose -f docker-compose.test.yml --profile element down -v
-v 会连同匿名卷一并清除,确保下次运行是干净环境。手动模式下常见的排障动作包括:
- 在
https://rc1用管理员登录,检查「管理 → 联邦」相关设置是否生效(Federation_Service_Enabled=true、域名为rc1); - 直接访问
https://element,用 Synapse 注册的账号(如alice/alice)登录,从 Matrix 原生客户端侧验证与 Rocket.Chat 用户互通; - 观察 Synapse 是否正常注册
admin、alice、bob、cleiton:直接查看容器日志docker compose -f docker-compose.test.yml logs hs1。
踩坑与排错速查
依据脚本与配置,以下几个问题是使用集成测试时的高频雷区:
- 忘改
/etc/hosts:rc1/hs1/element无法解析,容器间与测试进程都会失败。先补齐 README 中的三条 hosts 再运行; - HTTPS 证书不信任:手动用浏览器或 curl 访问
https://rc1时需信任docker-compose/traefik/certs/ca/rootCA.crt;测试进程本身通过NODE_EXTRA_CA_CERTS注入该根证书,无需额外操作; - 本地构建很慢或残留:本地模式会依次执行根目录
yarn build与apps/meteor的meteor build --server-only,耗时较长属正常;若只想验证逻辑而非最新代码,优先用--image rocketchat/rocket.chat:latest; - 环境起不来:脚本对 rc1 容器 60 秒未进入 running 会直接报错退出;对就绪探针最多等 240 秒(每 5 秒一次),超时会打印 rc1/hs1 最近 50 行日志后以非零码退出,请优先查看这两段日志定位是 Meteor 启动、Mongo 副本集还是 Synapse 的问题;
- 端口/镜像冲突:compose 暴露了宿主 80/443/8080 与 27017,若本地已有服务占用需先停掉,避免 Traefik 与 Mongo 端口冲突;
- CI 环境:脚本额外支持
--ci模式(保留容器、透传测试退出码),供流水线集成;默认本地模式则会完整清理,无需手动down。
小结
从 README 的一页说明出发,可以看到 federation-matrix 的集成测试并非简单的"起容器跑用例",而是一套刻意模拟真实跨联邦拓扑的编排:隔离网络 + Traefik 统一 HTTPS 入口、Synapse 自动播种多账号、Rocket.Chat 以 OVERWRITE_SETTING_* 注入联邦开关、就绪探针与信号清理的健壮脚本,以及按 DM/房间/权限/封禁/首接触拆分的中文可见的完整 E2E 矩阵。掌握 yarn test:integration 的参数组合与每个服务的角色后,无论是验证本地联邦代码改动、复现跨平台互通问题,还是从 Element 侧人工核对 Matrix 行为,都有了可复现的完整路径。后续阅读可从 tests/end-to-end 的具体用例入手,结合 FederationMatrix.ts 的消息转换与事件处理逻辑,深入理解每一处联邦行为背后的实现。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0631
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
video-shotcraftAI宣传片skill,使用 Remotion 制作电影级产品视频:提供106 张镜头配方卡和可复用的视频魔板。适用于 Claude Code 与 Codex以及所有其他智能体Markdown00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00