From 7c360167b33307d7403252d264e27b7a9bab1966 Mon Sep 17 00:00:00 2001 From: richjohnrambo Date: Fri, 14 Aug 2026 23:46:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...m_frontend_backend_1_11_unit_test_cases.md | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 .reviews/im_frontend_backend_1_11_unit_test_cases.md diff --git a/.reviews/im_frontend_backend_1_11_unit_test_cases.md b/.reviews/im_frontend_backend_1_11_unit_test_cases.md new file mode 100644 index 0000000..7b3e164 --- /dev/null +++ b/.reviews/im_frontend_backend_1_11_unit_test_cases.md @@ -0,0 +1,183 @@ +# IM 前后端对接文档 1-11 章单元测试用例 + +本文基于 `IM-前后端对接文档.md` 与当前实现代码整理,默认按 `httptest` + mock store + fake auth/media/push store 的方式落单元测试。 + +## 0. 验收准备 + +### 0.1 基础环境 + +| [ ] 项目 | 准备项 | 说明 | +|---|---|---| +| [ ] ENV-01 | 测试租户 A/B | A、B 都是 `active`,且准备一个 `suspended` 租户用于负向验证 | +| [ ] ENV-02 | 统一 API Key | 使用测试 API Key,覆盖 WS/HTTP 两类入口 | +| [ ] ENV-03 | 固定时间 | 对 Token、验证码、重置票据、过期时间使用可冻结时钟 | +| [ ] ENV-04 | Mock 存储 | `store.Users`、`store.Tenants`、`store.Verifications`、`store.Security`、`store.Files`、`store.Store` 可注入 mock/fake | +| [ ] ENV-05 | 文件沙箱 | 文件下载/上传路径使用临时目录,避免污染真实对象存储 | +| [ ] ENV-06 | 多设备上下文 | 至少准备同一用户的两个 session,验证退出/踢出/读回执聚合 | +| [ ] ENV-07 | 负向数据 | 同名 `alice`、同手机号、同群名、同 tag、同 file id 的 A/B 对照数据 | + +### 0.2 章节映射 + +| [ ] 章 | 主要入口/能力 | 代码证据 | 现有测试证据 | +|---|---|---|---| +| [ ] MAP-01 | 第1章 账号注册、登录与身份安全 | [server/main.go](/Users/superysh/im/im_server/server/main.go:780), [server/session.go](/Users/superysh/im/im_server/server/session.go:755), [server/user_verification_test.go](/Users/superysh/im/im_server/server/user_verification_test.go:19) | [server/session_test.go](/Users/superysh/im/im_server/server/session_test.go:38), [server/user_verification_test.go](/Users/superysh/im/im_server/server/user_verification_test.go:19), [server/auth/token/auth_token_test.go](/Users/superysh/im/im_server/server/auth/token/auth_token_test.go:1) | +| [ ] MAP-02 | 第2章 消息首页、全局导航与系统通知 | [server/main.go](/Users/superysh/im/im_server/server/main.go:791), [server/http.go](/Users/superysh/im/im_server/server/http.go:1) | 以 bootstrap / system notification handler 单测补齐 | +| [ ] MAP-03 | 第3章 单聊会话、会话建立与消息状态 | [server/main.go](/Users/superysh/im/im_server/server/main.go:821), [server/topic.go](/Users/superysh/im/im_server/server/topic.go:1) | [server/hub_tenant_test.go](/Users/superysh/im/im_server/server/hub_tenant_test.go:10), [server/topic_test.go](/Users/superysh/im/im_server/server/topic_test.go:1) | +| [ ] MAP-04 | 第4章 消息输入、媒体内容与消息操作 | [server/main.go](/Users/superysh/im/im_server/server/main.go:827), [server/datamodel.go](/Users/superysh/im/im_server/server/datamodel.go:1) | 需补 `pub/get/set/del/note` 行为单测 | +| [ ] MAP-05 | 第5章 通讯录、好友关系与黑名单 | [server/main.go](/Users/superysh/im/im_server/server/main.go:833), [server/main.go](/Users/superysh/im/im_server/server/main.go:835) | 需补 friend/block/qrcode 单测 | +| [ ] MAP-06 | 第6章 群聊创建、资料维护与成员治理 | [server/main.go](/Users/superysh/im/im_server/server/main.go:829), [server/topic.go](/Users/superysh/im/im_server/server/topic.go:1) | [server/hub_tenant_test.go](/Users/superysh/im/im_server/server/hub_tenant_test.go:10) | +| [ ] MAP-07 | 第7章 文件下载、收藏管理与聊天记录检索 | [server/main.go](/Users/superysh/im/im_server/server/main.go:824), [server/hdl_files.go](/Users/superysh/im/im_server/server/hdl_files.go:38) | [server/hdl_files_test.go](/Users/superysh/im/im_server/server/hdl_files_test.go:11), [server/media/fs/filesys_tenant_test.go](/Users/superysh/im/im_server/server/media/fs/filesys_tenant_test.go:11) | +| [ ] MAP-08 | 第8章 实时语音与视频通话 | [server/main.go](/Users/superysh/im/im_server/server/main.go:826), [server/calls.go](/Users/superysh/im/im_server/server/calls.go:1) | 需补 call 信令状态机单测 | +| [ ] MAP-09 | 第9章 企业工作台与办公协同 | [server/main.go](/Users/superysh/im/im_server/server/main.go:792), [server/main.go](/Users/superysh/im/im_server/server/main.go:796) | 需补 workbench/org/meeting/report/mailbox 单测 | +| [ ] MAP-10 | 第10章 个人资料、通用设置、隐私与青少年模式 | [server/main.go](/Users/superysh/im/im_server/server/main.go:812), [server/main.go](/Users/superysh/im/im_server/server/main.go:815) | [server/user_verification_test.go](/Users/superysh/im/im_server/server/user_verification_test.go:104) | +| [ ] MAP-11 | 第11章 反诈安全、举报与意见反馈 | [server/main.go](/Users/superysh/im/im_server/server/main.go:785), [server/main.go](/Users/superysh/im/im_server/server/main.go:798) | 需补 risk/abuse/feedback 单测 | + +### 0.3 现有护栏证据 + +| [ ] 证据 | 已覆盖的护栏 | 说明 | +|---|---|---| +| [ ] EVD-01 | Tenant 0 直接拒绝 | `store.ForTenant(0)` 已有测试 | +| [ ] EVD-02 | 同名 topic 按 tenant 隔离 | Hub tenant 测试已覆盖同名 `sys` 分离 | +| [ ] EVD-03 | 文件路径按 tenant 命名空间化 | tenant 文件路径测试已覆盖 | +| [ ] EVD-04 | Push channel 按 tenant 命名空间化 | tenant channel 测试已覆盖 | +| [ ] EVD-05 | 文件 HTTP 认证返回 Principal | 文件认证测试已覆盖 tenant/uid 绑定 | +| [ ] EVD-06 | Verification / reset 流程按 tenant 处理 | `user_verification_test.go` 已覆盖验证与重置主流程 | + +## 1. 第1章 账号注册、登录与身份安全 + +| [ ] ID | 场景 | 输入/操作 | 预期 | +|---|---|---|---| +| [ ] T01-01 | 企业码握手成功 | `hi.tenant=acme`,租户为 `active` | Session 只绑定一次 tenant;返回公开 tenant 信息,不暴露内部 `tenant_id` | +| [ ] T01-02 | 企业码缺失或非法 | `hi` 不带 tenant / 空白 / 超长 | 返回 400 类错误,Session 不绑定 tenant | +| [ ] T01-03 | 已绑定 Session 再发另一个 tenant | 先绑定 A,再发 B | 返回冲突类错误,tenant 不变化 | +| [ ] T01-04 | basic 登录同名跨租户 | A/B 都有 `alice`,分别用各自密码登录 | 只命中当前 tenant 的 auth 记录,token 携带当前 tenant | +| [ ] T01-05 | token 登录 tenant 不匹配 | A token 放进 B session | 认证失败,不写入 uid/authLvl | +| [ ] T01-06 | 注册验证码 tenant 隔离 | A、B 同手机号注册 | 只消费当前 tenant 的验证码记录,不串租户 | +| [ ] T01-07 | 找回密码 tenant 隔离 | A、B 同手机号触发重置 | 仅更新当前 tenant 用户,auth version 按当前 tenant 递增 | +| [ ] T01-08 | 实名/青少年/独立密码入口 | 无 tenant 或 tenant 不活跃 | 统一拒绝,不进入后续敏感流程 | + +## 2. 第2章 消息首页、全局导航与系统通知 + +| [ ] ID | 场景 | 输入/操作 | 预期 | +|---|---|---|---| +| [ ] C02-01 | bootstrap 只返回本租户菜单 | 调用 `bootstrap` | 功能开关、未读数、模块列表只来自当前 tenant | +| [ ] C02-02 | system notification 列表 | 查询/翻页已读未读 | 只返回当前 tenant 通知,分页游标稳定 | +| [ ] C02-03 | system notification read | 标记单条已读 | 只改当前 tenant 当前用户的 read state | +| [ ] C02-04 | conversation search | A 搜索 B 的联系人/会话 | 返回空或通用 NotFound,不泄露 B 的存在性 | +| [ ] C02-05 | 无网络/失效 token 恢复 | 模拟 token 失效后重连 | 进入统一错误分支,不误切 tenant | + +## 3. 第3章 单聊会话、会话建立与消息状态 + +| [ ] ID | 场景 | 输入/操作 | 预期 | +|---|---|---|---| +| [ ] T03-01 | P2P context 正常返回 | 查询同租户双方会话上下文 | `relationship`、`can_send`、`topic` 与当前 tenant 一致 | +| [ ] T03-02 | 非好友/黑名单发消息 | 在 `can_send=false` 下调用 pub | 服务端拒绝,不产生消息 seq | +| [ ] T03-03 | read/recv 回执推进 | 连续提交 `note read/recv` | 只允许单调推进,不回退读游标 | +| [ ] T03-04 | 删除好友后历史保留 | 删除好友后再查历史消息 | 历史还在,但后续发送被拒绝 | +| [ ] T03-05 | 跨租户 topic 访问 | 已知 B topic 订阅/读/写 | 统一 NotFound/Denied,不进入 Hub 缓存 | +| [ ] T03-06 | 主题状态切换 | attach/leave/reattach | session/topic 状态机不被错误 tenant 影响 | + +## 4. 第4章 消息输入、媒体内容与消息操作 + +| [ ] ID | 场景 | 输入/操作 | 预期 | +|---|---|---|---| +| [ ] C04-01 | 文本消息 schema 校验 | `x-im-schema=1`、`x-im-type=text`、`x-im-client-mid` | 通过并保持 client-mid 幂等 | +| [ ] C04-02 | 媒体消息字段校验 | image/video/voice/file 的 `content` | 必填字段缺失或超长时拒绝 | +| [ ] C04-03 | @成员与 @all | 指定群成员 / `mention_all` | 成员过滤正确,越权 `@all` 被拒绝 | +| [ ] C04-04 | 编辑/撤回/删除 | 对同一消息进行修改或撤回 | 只允许符合时限和角色的操作 | +| [ ] C04-05 | 合并转发结构 | bundle/逐条转发 | 快照字段稳定,源消息与目标消息分离 | +| [ ] C04-06 | 媒体消息重复提交 | 重试同一 `client_mid` | 返回首次写入结果,不重复落库 | + +## 5. 第5章 通讯录、好友关系与黑名单 + +| [ ] ID | 场景 | 输入/操作 | 预期 | +|---|---|---|---| +| [ ] C05-01 | 用户搜索 tenant 隔离 | A 搜索 B 仅有的账号/tag | 返回空结果,不提示跨租户命中 | +| [ ] C05-02 | 二维码解析 | 用 add_friend token 解析 | 只返回当前 tenant 可见的公开资料 | +| [ ] C05-03 | 好友申请幂等 | 同一请求重复提交 | 返回原申请记录,不重复创建 | +| [ ] C05-04 | 好友同意/拒绝 | 审批 inbound request | 双方关系和 P2P topic 同步更新 | +| [ ] C05-05 | 拉黑/解除拉黑 | `PUT/DELETE /blocks/{user_id}` | 只影响当前 tenant 当前用户关系 | +| [ ] C05-06 | 删除好友 | `DELETE /friends/{user_id}` | 历史消息不删,后续会话发送被拒绝 | + +## 6. 第6章 群聊创建、资料维护与成员治理 + +| [ ] ID | 场景 | 输入/操作 | 预期 | +|---|---|---|---| +| [ ] C06-01 | 创建群 | 创建新 group topic | topic、group settings、owner、subscription 同 tenant 落库 | +| [ ] C06-02 | 邀请/审批入群 | 邀请 B tenant 用户进 A 群 | 统一拒绝,不产生部分写入 | +| [ ] C06-03 | 群管理员变更 | 提升/降级成员角色 | 仅允许本群本 tenant 成员,ACL 一致 | +| [ ] C06-04 | 群主转让 | 指定新 owner | 事务内同步业务真源和 Topic Owner | +| [ ] C06-05 | 群禁言/全员禁言 | muted member 发消息 | 服务端拒绝,其他成员不可见 | +| [ ] C06-06 | 群文件/成员列表 | 查询群成员、群文件 | 只返回当前 tenant 当前群成员 | + +## 7. 第7章 文件下载、收藏管理与聊天记录检索 + +| [ ] ID | 场景 | 输入/操作 | 预期 | +|---|---|---|---| +| [ ] C07-01 | 文件上传 principal | HTTP/gRPC 文件上传 | `RequestPrincipal` 必须带 tenant/uid,落库 tenant 正确 | +| [ ] C07-02 | 文件下载授权 | 用 A 用户访问 B file id | 返回 403/404,不暴露 location | +| [ ] C07-03 | 收藏去重 | 同一 `topic+seq` 重复收藏 | 只新增一条,返回 existing 计数 | +| [ ] C07-04 | 收藏转发 | 对已收藏消息做转发 | 保持 source snapshot,不越权扩散 | +| [ ] C07-05 | 会话/消息搜索 | 搜索关键字、类型、文件 | 只返回当前 tenant 且有读权限的结果 | +| [ ] C07-06 | 垃圾清理 | 过期未使用文件清理 | 只清当前 tenant,不误删其他 tenant 文件 | + +## 8. 第8章 实时语音与视频通话 + +| [ ] ID | 场景 | 输入/操作 | 预期 | +|---|---|---|---| +| [ ] T08-01 | 发起通话 | `call` invite / note started | 生成稳定 `callId`,同 tenant 双方可见 | +| [ ] T08-02 | 接听/拒绝/挂断 | accept / reject / hang-up | 状态转换正确,结束原因稳定 | +| [ ] T08-03 | 超时结束 | 不接听直到超时 | 服务端替换为 missed/timeout 结果 | +| [ ] T08-04 | 多设备回放 | 同用户多个 session | 只向合法 session 广播,不串 tenant | +| [ ] T08-05 | 跨租户呼叫 | A 呼叫 B tenant 用户 | 统一拒绝,不创建有效通话记录 | + +## 9. 第9章 企业工作台与办公协同 + +| [ ] ID | 场景 | 输入/操作 | 预期 | +|---|---|---|---| +| [ ] B09-01 | workbench 模块列表 | 查询工作台 | 模块、权限、未读数只取当前 tenant | +| [ ] B09-02 | 组织树查询 | 查部门根节点/子节点/成员 | 只返回当前 tenant 组织结构 | +| [ ] B09-03 | 会议创建/变更/取消 | 创建会议并更新参会人 | 幂等、通知、审计都在当前 tenant | +| [ ] B09-04 | 日报/月报草稿与统计 | 创建、提交、统计、提醒 | 统计范围受 tenant 与管理权限约束 | +| [ ] B09-05 | 总经理信箱/工作台入口 | 查询配置与提交 | 匿名/必填字段/附件策略按 tenant 配置 | + +## 10. 第10章 个人资料、通用设置、隐私与青少年模式 + +| [ ] ID | 场景 | 输入/操作 | 预期 | +|---|---|---|---| +| [ ] T10-01 | me/profile 读取与更新 | 查询并 patch 个人资料 | 只允许当前用户当前 tenant 数据更新 | +| [ ] T10-02 | privacy 更新 | 修改隐私项 | 版本控制正确,其他设备能收到变更 | +| [ ] T10-03 | youth mode 开关 | 启用/关闭青少年模式 | 需要 action token / 独立密码,tenant 一致 | +| [ ] T10-04 | independent password | 设置/验证独立密码 | 明文不落库,不跨租户复用 | +| [ ] T10-05 | push token 绑定 | 更新设备 push token | `(tenant_id, uid, device_id)` 维度唯一 | +| [ ] T10-06 | app release / settings menu | 查询版本与设置菜单 | 返回当前 tenant 配置,不混入别的企业开关 | + +## 11. 第11章 反诈安全、举报与意见反馈 + +| [ ] ID | 场景 | 输入/操作 | 预期 | +|---|---|---|---| +| [ ] B11-01 | URL 风险检查 | 检查外链 | 返回 allow/warn/block,带租户上下文 | +| [ ] B11-02 | 风险挑战确认 | `continue/cancel` | 只消费当前租户当前 challenge | +| [ ] B11-03 | 举报原因与提交 | 读取原因并提交举报 | reason、证据、目标对象按 tenant 存档 | +| [ ] B11-04 | 反馈配置与提交 | 查询反馈配置并提交反馈 | 附件、联系方式、诊断信息按 tenant 策略处理 | +| [ ] B11-05 | 系统通知联动 | 风险/举报结果产生通知 | 只推当前 tenant 相关用户,不跨租户扩散 | + +## 12. 高风险迁移确认点 + +| [ ] ID | 确认点 | 为什么要测 | 预期 | +|---|---|---|---| +| [ ] RISK-01 | Token / Session tenant 一致性 | 这是全链路身份根 | 任意篡改都拒绝 | +| [ ] RISK-02 | 文件认证 Principal | 文件链路最容易只剩 UID | 没 tenant 直接失败 | +| [ ] RISK-03 | 同名 `sys` / Topic 隔离 | 最容易发生缓存串租户 | 不同 tenant 命中不同对象 | +| [ ] RISK-04 | 事务内幂等 | 验证码、好友、群审批、会议、举报都依赖 | 重试不重复写 | +| [ ] RISK-05 | 搜索二次 ACL | 索引命中不代表可见 | 返回前再做权限过滤 | +| [ ] RISK-06 | Push / 回调 / 外部服务 | 外部 side-effect 最易丢 tenant | 出站上下文保持 tenant | +| [ ] RISK-07 | 旧请求重放 | 防止用旧参数跨 tenant 复用 | 统一按当前 tenant 拒绝 | +| [ ] RISK-08 | 失败回滚 | 群主转让、入群、文件关联等 | 只要一处失败就全回滚 | + +## 13. 建议补测顺序 + +1. 先补第 1 章和第 7 章,因为它们是登录态与文件安全的根。 +2. 再补第 3、5、6 章,把联系人、群和消息主链路闭环。 +3. 然后补第 8、9、10、11 章,覆盖通话、工作台、设置和安全合规模块。 +4. 最后做跨章回归:同名数据双租户、同 token 重放、同 file id 访问、同 topic 搜索。