报告日期: 2026-05-15(新增用户凭证票据机制 CreateUser/ResetPassword/FetchUserCredentials) 测试范围: REST API (go-zero) + gRPC + Model 层 (自定义方法 + _gen.go 模板生成) + Logic 单元测试 + util 层 + 访问控制 + UserDetailsLoader + 中间件 测试用例设计详见 test-design.md 执行命令:
go test -count=1 -timeout 600s ./...
| 指标 | 数值 |
|---|---|
| 测试包总数 | 28 |
| TC 用例总数 (test-design.md) | 1065 |
| 顶层测试函数数 (Functions) | 1170 |
测试执行事件总数 (含 t.Run 子用例) |
1309 |
| ✅ 通过 | 1307 |
| ⏭️ 跳过 | 2 |
| ❌ 失败 | 0(本轮全绿) |
| 通过率 (TC 维度) | 100%(扣除 2 条不可达防御分支 Skip) |
| Logic 层语句覆盖率 | 87.2%(go tool cover -func 统计) |
| 测试包 | 状态 | 耗时 |
|---|---|---|
| internal/handler | ✅ ok | 1.339s |
| internal/handler/auth | ✅ ok | 3.744s |
| internal/handler/minio | ✅ ok | 2.124s |
| internal/handler/product | ✅ ok | 2.597s |
| internal/handler/pub | ✅ ok | 3.199s |
| internal/loaders | ✅ ok | 4.418s |
| internal/logic/auth | ✅ ok | 13.685s |
| internal/logic/dept | ✅ ok | 6.231s |
| internal/logic/member | ✅ ok | 7.291s |
| internal/logic/minio | ✅ ok | 8.127s |
| internal/logic/perm | ✅ ok | 9.476s |
| internal/logic/product | ✅ ok | 18.959s |
| internal/logic/pub | ✅ ok | 14.051s |
| internal/logic/role | ✅ ok | 12.803s |
| internal/logic/user | ✅ ok | 20.844s |
| internal/middleware | ✅ ok | 14.374s |
| internal/model/dept | ✅ ok | 15.051s |
| internal/model/perm | ✅ ok | 14.717s |
| internal/model/product | ✅ ok | 14.814s |
| internal/model/productmember | ✅ ok | 14.115s |
| internal/model/role | ✅ ok | 12.892s |
| internal/model/roleperm | ✅ ok | 12.404s |
| internal/model/user | ✅ ok | 20.141s |
| internal/model/userperm | ✅ ok | 11.709s |
| internal/model/userrole | ✅ ok | 8.933s |
| internal/response | ✅ ok | 8.987s |
| internal/server | ✅ ok | 9.439s |
| internal/util | ✅ ok | 9.082s |
| TC 编号 | 跳过原因 |
|---|---|
| TC-0263 | JWT claims 类型断言防御性分支,在 jwt.ParseWithClaims(&Claims{}) 下不可达 |
| — | TestMinioUpload_EmptyFileType:Minio 空文件类型防御分支,测试环境无 Minio 实例 |
本轮无业务缺陷。仅保留 1 条 pre-existing、与被测代码无关的并发 flake 作为存档。
| TC 编号 | 失败现象 | 根因 | 跟进建议 |
|---|---|---|---|
TC-0820(UserModel_IncrementTokenVersionIfMatch) |
TestSysUserModel_IncrementTokenVersionIfMatch_ConcurrentSingleWinner 在整包并发压下偶发 circuit breaker is open(go-zero breaker)失败 |
本用例靠 wg+8 goroutine 同时冲同一行走 CAS UPDATE ... WHERE tokenVersion=?,在整包全量并发压下 go-zero SQL 断路器被其它测试累计的错误触达打开,导致 8 路里若干路直接被 breaker 短路拒绝;-run 单独跑则断路器计数窗口没攒满,必过 |
在测试 setup 里显式重置 breaker 统计(或注入允许更高错误率的 breaker 配置),也可在断言里把 circuit breaker is open 视作"并发压力副作用"跳过重试;非业务 bug,生产路径的 CAS 正确性已由 _Match / _Mismatch_NoSideEffect 两条稳定用例覆盖 |
已修复的回归点:上一轮报告中的 TC-1078
TestBindRoles_Vs_DeleteRole_NoOrphanRows文案 flake,本轮随bindRolesLogic三路径统一为包含无效的角色ID的改动(L-R14-2)一并收敛;并发断言现已与新文案对齐,单独 / 整包执行均稳定 pass。本轮变更:POST /api/user/bindRoles请求体新增productCode字段。SUPER_ADMIN 的 JWT 中productCode为空字符串,原实现直接从 JWT context 读取导致 member 查询失败("目标用户不是当前产品的成员")。修复后 logic 优先使用req.ProductCode(非空时覆盖 JWT context 值),所有BindRolesReq测试用例已同步补充ProductCode字段。本轮新增:用户凭证票据机制(CreateUser 移除 Password 字段改为服务端生成 + ticket 一次性领取、ResetPassword、FetchUserCredentials),新增 TC-1280 ~ TC-1299 共 20 条用例。同时修复
userrole包 4 条测试因FindRoleIdsByUserId新增INNER JOIN sys_role过滤导致的 pre-existing 失败(测试数据未在sys_role表中创建对应角色记录)。
以下章节按
test-design.md的章节顺序枚举每一个 TC 的编号、测试场景与执行结果。
POST /api/auth/login| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0001 | 正常登录(普通用户+productCode) | ✅ pass |
| TC-0002 | 正常登录-带productCode+ADMIN成员 | ✅ pass |
| TC-0003 | 超管通过产品端登录被拒绝 | ✅ pass |
| TC-0004 | 超管无productCode被拒绝 | ✅ pass |
| TC-0005 | 用户不存在 | ✅ pass |
| TC-0006 | DB异常(非ErrNotFound) | ✅ pass |
| TC-0007 | 密码错误 | ✅ pass |
| TC-0008 | 账号冻结 | ✅ pass |
| TC-0009 | 非产品成员 | ✅ pass |
| TC-0010 | DEVELOPER成员 | ✅ pass |
| TC-0011 | SQL注入 | ✅ pass |
| TC-0012 | 缺少必填字段 | ✅ pass |
| TC-0013 | 产品成员被禁用时拒绝登录 | ✅ pass |
| TC-0014 | 产品被禁用时拒绝登录 | ✅ pass |
| TC-0751 | 用户名不存在 + 任意密码 | ✅ pass |
| TC-0752 | 用户名存在但密码错 | ✅ pass |
| TC-0753 | 登录限流 key 必须基于 ip:username |
✅ pass |
| TC-0838 | 用户冻结 + 错误密码 | ✅ pass |
| TC-0839 | 用户冻结 + 正确密码 | ✅ pass |
| TC-0840 | 超管走产品端登录 + 错误密码 | ✅ pass |
| TC-0841 | 超管走产品端登录 + 正确密码 | ✅ pass |
| TC-0842 | 用户名不存在 | ✅ pass |
| TC-1213 | cap.js 未启用 + 验证码为空 | ✅ pass |
| TC-1214 | cap.js 未启用 + 验证码错误/过期 | ✅ pass |
| TC-1215 | cap.js 未启用 + 验证码正确 → 正常登录 | ✅ pass |
| TC-1250 | cap.js 已启用时传统接口被拒绝 | ✅ pass |
POST /api/auth/adminLogin| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0015 | 超管正常登录 | ✅ pass |
| TC-0016 | 普通用户被拒绝 | ✅ pass |
| TC-0017 | managementKey无效 | ✅ pass |
| TC-0018 | managementKey为空 | ✅ pass |
| TC-0019 | 用户不存在 | ✅ pass |
| TC-0020 | 密码错误 | ✅ pass |
| TC-0021 | 账号冻结 | ✅ pass |
| TC-0022 | 不带productCode时perms为空 | ✅ pass |
| TC-0023 | 缺少必填字段 | ✅ pass |
| TC-0024 | SQL注入username | ✅ pass |
| TC-0025 | adminLogin 用户名限流 | ✅ pass |
| TC-0710 | 同 IP,产品登录用尽配额后管后登录仍放行 | ✅ pass |
| TC-0781 | 不存在用户登录管理后台响应时间恒定 | ✅ pass |
| TC-0834 | 相同 IP + 相同 username 连续打满 quota | ✅ pass |
| TC-0835 | 同 username 但换远端 IP | ✅ pass |
| TC-0836 | clientIP 缺失(未挂 RateLimit 中间件) | ✅ pass |
| TC-0837 | managementKey 无效路径不得消耗 username 配额 | ✅ pass |
| TC-1008 | 非超管+错密码 vs 用户不存在 | ✅ pass |
| TC-1009 | 非超管+正确密码 | ✅ pass |
| TC-1010 | 两条 dummy bcrypt 分支时序 | ✅ pass |
| TC-1216 | cap.js 未启用 + 验证码为空 | ✅ pass |
| TC-1217 | cap.js 未启用 + 验证码错误/过期 | ✅ pass |
| TC-1218 | cap.js 未启用 + 验证码正确 → 超管正常登录 | ✅ pass |
| TC-1251 | cap.js 已启用时传统接口被拒绝 | ✅ pass |
POST /api/auth/refreshToken| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0026 | 正常刷新 | ✅ pass |
| TC-0027 | 不带productCode(回退) | ✅ pass |
| TC-0028 | token无效 | ✅ pass |
| TC-0029 | 用户已删除 | ✅ pass |
| TC-0030 | 账号冻结 | ✅ pass |
| TC-0031 | 超管+productCode(token中已含相同pc) | ✅ pass |
| TC-0032 | 尝试切换产品被拒绝 | ✅ pass |
| TC-0033 | TokenVersion不匹配时拒绝刷新 | ✅ pass |
| TC-0034 | 使用accessToken作为refreshToken被拒绝 | ✅ pass |
| TC-0035 | 产品成员已移除时拒绝刷新 | ✅ pass |
| TC-0720 | 正常登出 | ✅ pass |
| TC-0721 | 未登录调用 /auth/logout | ✅ pass |
| TC-0722 | 同一用户连续两次 logout | ✅ pass |
| TC-0832 | 静态 wiring 检查:routes.go 中 /auth/refreshToken 所在 rest.WithMiddlewares(...) 块必须包含 serverCtx.RefreshTokenRateLimit |
✅ pass |
| TC-0833 | 行为验证:构造等价中间件链(quota=1),同 IP 连打 2 次;再换 IP 打 1 次 | ✅ pass |
| TC-0983 | 成功路径:DB tokenVersion +1 且新 access/refresh claims.TokenVersion 严格等于 DB 新值 | ✅ pass |
| TC-0984 | CAS 不命中("其他并发赢家已把 DB 推到 version=1"后再来一次 claims=0) | ✅ pass |
| TC-0985 | 多轮链式刷新 + 旧 token 重放 | ✅ pass |
| TC-1066 | helper happy path:返回新 access+refresh、DB tokenVersion +1、user cache Clean | ✅ pass |
| TC-1067 | helper:claims.TokenVersion 与 DB 不一致 → ErrTokenVersionMismatch |
✅ pass |
| TC-1068 | helper:用户已删除 → ErrTokenVersionMismatch |
✅ pass |
| TC-1069 | 跨协议互认:HTTP 签出的 refreshToken 能被 gRPC RefreshToken 无缝续签 | ✅ pass |
| TC-1070 | 跨协议互认:gRPC 签出的 refreshToken 能被 HTTP RefreshToken 无缝续签 | ✅ pass |
| TC-1071 | gRPC 重放:旧 rtV0 已被用过一次,再发给 gRPC 必须 Unauthenticated(而非 Internal) | ✅ pass |
| TC-1117 | M-R14-1:RotateRefreshToken post-commit UD 缓存清理与请求 ctx 解耦 | ✅ pass |
POST /api/perm/sync| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0036 | 全部新增 | ✅ pass |
| TC-0037 | 更新已有(名称变更) | ✅ pass |
| TC-0038 | 无变化 | ✅ pass |
| TC-0039 | 禁用权限重启 | ✅ pass |
| TC-0040 | 移除不在列表的权限 | ✅ pass |
| TC-0041 | 空perms数组被拒绝 | ✅ pass |
| TC-0042 | 验证disabled返回值 | ✅ pass |
| TC-0043 | appKey无效 | ✅ pass |
| TC-0044 | appSecret错误 | ✅ pass |
| TC-0045 | 产品已禁用 | ✅ pass |
| TC-0046 | 大批量(1000条) | ✅ pass |
| TC-0047 | 重复code去重 | ✅ pass |
| TC-0048 | 事务保护-中途失败回滚 | ✅ pass |
| TC-0807 | FindMapByProductCodeWithTx 与非事务版返回等价 |
✅ pass |
| TC-0808 | 产品无权限时返回 | ✅ pass |
| TC-0809 | LockByCodeTx 对存在 code 返回完整行 |
✅ pass |
| TC-0810 | 对不存在 code | ✅ pass |
| TC-0811 | 两个事务同时锁同一行 | ✅ pass |
| TC-0826 | 同一 perm code 在 req 中重复 | ✅ pass |
| TC-0843 | mock 断言事务内必调用 LockByCodeTx |
✅ pass |
| TC-0844 | mock LockByCodeTx 返回 sqlx.ErrNotFound |
✅ pass |
| TC-0845 | mock LockByCodeTx 返回通用 error |
✅ pass |
| TC-0979 | REST:tx 内 LockByCodeTx → ErrNotFound |
✅ pass |
| TC-0980 | REST 反例:未映射 se.Code=500 |
✅ pass |
| TC-0981 | gRPC:同 LockByCodeTx ErrNotFound | ✅ pass |
| TC-0982 | gRPC 反例:未映射 code | ✅ pass |
| TC-1021 | 既有 404 路径用例的 LockByCodeTx mock 显式携带 Status=1 |
✅ pass |
| TC-1022 | Dedup / mock / TxLock 三路径下事务内 Status 复核全覆盖 | ✅ pass |
| TC-1023 | gRPC SyncPermissions 入口同样落入 Status=1 契约 |
✅ pass |
| TC-1063 | 纯新增(updated=0, disabled=0)→ 必须触发 CleanByProduct(M-R17-1 语义收敛) | ✅ pass |
| TC-1064 | 至少一条 update(code 存在但 name/Status/Sort 变更)→ 必须触发 CleanByProduct | ✅ pass |
| TC-1065 | 至少一条 disable(列表里不含的 perm 被置 Disabled)→ 必须触发 CleanByProduct | ✅ pass |
| TC-1118 | M-R14-1:ExecuteSyncPerms post-commit CleanByProduct 与请求 ctx 解耦 | ✅ pass |
POST /api/auth/userInfo| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0049 | 正常获取-含productCode | ✅ pass |
| TC-0050 | 不含productCode | ✅ pass |
| TC-0051 | 未登录 | ✅ pass |
| TC-0052 | token过期 | ✅ pass |
| TC-0053 | userId=0 | ✅ pass |
POST /api/auth/changePassword| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0054 | 正常修改 | ✅ pass |
| TC-0055 | mustChangePassword重置 | ✅ pass |
| TC-0056 | 原密码错误 | ✅ pass |
| TC-0057 | 新密码少于8字符 | ✅ pass |
| TC-0058 | 新密码恰好8字符(含大小写+数字) | ✅ pass |
| TC-0059 | 新密码空字符串 | ✅ pass |
| TC-0060 | 新密码超过72字符 | ✅ pass |
| TC-0061 | 新密码恰好72字符 | ✅ pass |
| TC-0062 | 新旧密码相同 | ✅ pass |
| TC-0063 | 用户不存在 | ✅ pass |
| TC-0769 | ChangePassword 超过 TokenOpLimiter 配额 | ✅ pass |
| TC-0770 | 冻结用户调用 ChangePassword | ✅ pass |
| TC-0771 | 原密码错误时记录日志 | ✅ pass |
| TC-1015 | UpdatePassword 返回 ErrUpdateConflict 时必须回 409 |
✅ pass |
| TC-1016 | 非 ErrUpdateConflict 的 raw error 仍需透传(由 rest 兜 500) |
✅ pass |
| TC-1039 | Model 层正向:expectedUpdateTime 与 DB 一致 → 成功 + tokenVersion+1 + updateTime 前进 |
✅ pass |
| TC-1040 | Model 层 TOCTOU:调用方持有"陈旧的 expectedUpdateTime" | ✅ pass |
| TC-1041 | Model 层并发:同一 expectedUpdateTime 两 goroutine 并行 CAS | ✅ pass |
| TC-1042 | Logic 层 E2E:同一 user 连续两次用 "同一旧密码 P0" 发起 ChangePassword,第二次必须 400 "旧密码错误" | ✅ pass |
| TC-1043 | Logic 层 mock:ChangePassword 必须把"外层 FindOne 拿到的 user.UpdateTime" 原封不动透传给 Model 层 | ✅ pass |
| TC-1179 | OldPassword==NewPassword 必须在 bcrypt.CompareHashAndPassword 之前被拦截(L-R17-4) |
✅ pass |
POST /api/product/create| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0064 | 正常创建 | ✅ pass |
| TC-0065 | 事务回滚-用户创建失败 | ✅ pass |
| TC-0066 | 事务回滚-成员创建失败 | ✅ pass |
| TC-0067 | 编码已存在 | ✅ pass |
| TC-0068 | 并发创建同编码 | ✅ pass |
| TC-0069 | createProduct 含空格被拒绝 | ✅ pass |
| TC-0070 | createProduct 含特殊字符被拒绝 | ✅ pass |
| TC-0071 | createProduct 全中文被拒绝 | ✅ pass |
| TC-0072 | createProduct 纯数字开头被拒绝 | ✅ pass |
| TC-0073 | createProduct 空字符串被拒绝 | ✅ pass |
| TC-0074 | createProduct 长度>64 被拒绝 | ✅ pass |
| TC-0075 | createProduct 合法编码(含下划线/中划线/数字) | ✅ pass |
| TC-0774 | appKey 长度=32 hex字符 (16字节) | ✅ pass |
| TC-0775 | appSecret 长度=64 hex字符 (32字节) | ✅ pass |
| TC-0776 | 初始管理员密码长度=24 hex字符 (12字节) | ✅ pass |
| TC-0827 | mock InsertWithTx 返回 mysql error 1062,message 不含 "uk_code" |
✅ pass |
| TC-0901 | happy path:超管用有效 ticket 取回初始凭据 | ✅ pass |
| TC-0902 | 相同 ticket 二次消费 | ✅ pass |
| TC-0903 | ticket 为空 | ✅ pass |
| TC-0904 | ticket 未知 | ✅ pass |
| TC-0905 | 非超管调用 | ✅ pass |
| TC-0906 | 未登录调用 | ✅ pass |
| TC-0907 | Redis 中 payload 被人为破坏 | ✅ pass |
| TC-0908 | Redis key 结构正确 | ✅ pass |
| TC-0909 | TTL 与响应 expiresAt 一致 | ✅ pass |
| TC-0910 | 并发消费同一 ticket | ✅ pass |
| TC-0911 | CreateProductResp JSON 不含 appSecret/adminPassword | ✅ pass |
| TC-0912 | CreateProductResp 必含 credentialsTicket + credentialsExpiresAt | ✅ pass |
| TC-0961 | body 非法 JSON | ✅ pass |
| TC-0962 | 无登录上下文 | ✅ pass |
| TC-0963 | 非超管 ctx | ✅ pass |
| TC-0964 | 超管 + 空 ticket | ✅ pass |
| TC-0965 | 超管 + 未知 ticket | ✅ pass |
| TC-0966 | 超管 + 已落地 ticket | ✅ pass |
| TC-0967 | 静态 wiring:JwtAuth 绑定 | ✅ pass |
| TC-0968 | 静态反证:不得挂到限流组 | ✅ pass |
| TC-0976 | Redis 整个不可达(SetexCtx 永久失败) |
✅ pass |
| TC-0977 | Redis 失败 + 补偿成功后以同 Code 重建 | ✅ pass |
| TC-0978 | 补偿顺序显式校验(child → parent) | ✅ pass |
| TC-1029 | seedAdminDept(t, ctx, svcCtx) 集中化 |
✅ pass |
| TC-1030 | CreateProduct 所有正向用例携带 AdminDeptId 后行为不变 |
✅ pass |
| TC-1031 | FetchInitialCredentials 票据消费路径携带 AdminDeptId 后行为不变 |
✅ pass |
| TC-1032 | Redis 降级补偿链路径携带 AdminDeptId 后行为不变 |
✅ pass |
| TC-1033 | 冲突路径下 SysDeptModel.FindOne 返 Status=1 且 AdminDeptId 透传 |
✅ pass |
| TC-1034 | mock 侧两处 CreateProductReq 补齐 AdminDeptId 字段 |
✅ pass |
| TC-1035 | 一次性票据 AdminPassword 长度=16(不再是旧的 24) |
✅ pass |
| TC-1202 | 未传 avatar 时 admin 用户行的 avatar 列在 DB 层必须是 SQL NULL(L-R17-2) |
✅ pass |
| TC-1203 | CreateProduct 事务内 FindOneForShareTx(adminDeptId)==ErrNotFound 时必须 400 "管理员部门不存在或已删除",product/user/product_member 三张表 InsertWithTx 均不得被调用(H-R17-1) |
✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0076 | 正常更新 | ✅ pass |
| TC-0077 | 不存在 | ✅ pass |
| TC-0078 | 不传status | ✅ pass |
| TC-0090 | updateProduct 非法状态值被拒绝 | ✅ pass |
| TC-0850 | MEMBER 调 ProductList | ✅ pass |
| TC-0851 | MEMBER 调 ProductList 且 ProductCode=="" |
✅ pass |
| TC-0852 | MEMBER 调 ProductDetail 查他产品 | ✅ pass |
| TC-0853 | MEMBER 调 ProductDetail 查自己产品 | ✅ pass |
| TC-0854 | 超管调 ProductDetail | ✅ pass |
| TC-0855 | MEMBER 调 DeptTree | ✅ pass |
| TC-0856 | MEMBER 调 DeptTree 且 DeptPath="" | ✅ pass |
| TC-0857 | 产品 ADMIN 调 DeptTree 仅见 DeptPath 子树 | ✅ pass |
| TC-1128 | SuperAdmin 调 DeptTree 仍见完整树 | ✅ pass |
| TC-1129 | DEVELOPER 调 DeptTree 同样剪枝到 DeptPath 子树 | ✅ pass |
| TC-1138 | Enabled→Disabled 产品时,所有启用成员 tokenVersion 全部 +1;禁用成员不受影响 | ✅ pass |
| TC-1139 | Disabled→Enabled 时 tokenVersion 不变(重启用不吊销 session) | ✅ pass |
| TC-1140 | 仅改 Name / Remark 不改 Status 时 tokenVersion 不变 | ✅ pass |
| TC-1141 | 禁用 P1 不得影响只属于 P2 的用户 tokenVersion(跨产品隔离) | ✅ pass |
| TC-1142 | 禁用无启用成员产品时仍成功,产品行落盘 Disabled | ✅ pass |
| TC-1143 | post-commit 失效 sysProduct 的 id / appKey / code 三把低层缓存 | ✅ pass |
POST /api/dept/create| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0091 | 创建顶级部门 | ✅ pass |
| TC-0092 | 创建子部门 | ✅ pass |
| TC-0093 | 父部门不存在 | ✅ pass |
| TC-0094 | 不传DeptType默认NORMAL | ✅ pass |
| TC-0095 | 传DeptType=DEV | ✅ pass |
| TC-0096 | 事务内FindOneWithTx可见性 | ✅ pass |
| TC-0097 | 事务回滚-Insert失败 | ✅ pass |
| TC-0098 | 事务回滚-UpdateWithTx失败 | ✅ pass |
| TC-0099 | 多层嵌套(5层) | ✅ pass |
| TC-0100 | 通过Logic创建+验证Path | ✅ pass |
| TC-1084 | 父部门已 Disabled → 事务内 FindOneForShareTx 复核拒绝 | ✅ pass |
| TC-1085 | 父部门 Enabled 正向路径 + parentPath 来自事务内 snapshot | ✅ pass |
| TC-1086 | CreateDept × UpdateDept(禁用父) 并发 6 轮 | ✅ pass |
| TC-1202 | CreateDept Sort 超出 [-100000, 100000] 被拒绝(负向+边界正向)(L-R18-5) | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0101 | 正常更新 | ✅ pass |
| TC-0102 | 不存在 | ✅ pass |
| TC-0103 | DeptType NORMAL→DEV | ✅ pass |
| TC-0104 | DeptType无效值返回错误 | ✅ pass |
| TC-0105 | DeptType变更时级联清除子部门用户缓存 | ✅ pass |
| TC-0106 | 正常删除(无子部门) | ✅ pass |
| TC-0107 | 有子部门 | ✅ pass |
| TC-0108 | 不存在的部门 | ✅ pass |
| TC-0109 | 部门下有关联用户 | ✅ pass |
| TC-0714 | DeptType/Status 未变更时不清缓存 | ✅ pass |
| TC-0715 | 乐观锁冲突返回 ErrConflict | ✅ pass |
| TC-0759 | 10 goroutine 同时 UpdateWithOptLock 同一行 | ✅ pass |
| TC-0766 | 删除有子部门的部门(FOR UPDATE 锁定读) | ✅ pass |
| TC-0767 | 删除有关联用户的部门(FOR UPDATE 锁定读) | ✅ pass |
| TC-0768 | CreateDept 父部门 FOR SHARE 锁生效 | ✅ pass |
| TC-0846 | CleanByUserIds 批量清理多用户缓存 |
✅ pass |
| TC-0847 | CleanByUserIds 空 ids 切片 |
✅ pass |
| TC-0848 | UpdateDept 改 deptType 时调 CleanByUserIds |
✅ pass |
| TC-0849 | UpdateDept 的 FindIdsByDeptId 失败 |
✅ pass |
| TC-1174 | DeptType DEV→NORMAL 批量递增部门下所有成员 tokenVersion | ✅ pass |
| TC-1175 | DEV 部门 Status Enabled→Disabled 批量递增 tokenVersion | ✅ pass |
| TC-1176 | NORMAL 部门 Status Enabled→Disabled 批量递增 tokenVersion | ✅ pass |
| TC-1177 | NORMAL→DEV(升权方向)tokenVersion 保持不变 | ✅ pass |
| TC-1178 | Status Disabled→Enabled(恢复启用)tokenVersion 保持不变 | ✅ pass |
| TC-1200 | DeleteDept 成功提交后必须 post-commit 显式失效 sysDept:id 缓存(H-R17-2) |
✅ pass |
| TC-1203 | UpdateDept Sort 超出 [-100000, 100000] 被拒绝,DB 中 Sort 值不变(L-R18-5) | ✅ pass |
POST /api/perm/list| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0113 | 正常查询 | ✅ pass |
| TC-0114 | 默认分页 | ✅ pass |
| TC-0115 | pageSize超过上限 | ✅ pass |
| TC-0116 | 不存在的productCode | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0117 | 正常创建 | ✅ pass |
| TC-0118 | 重复角色名 | ✅ pass |
| TC-0119 | 并发同名创建 | ✅ pass |
| TC-0120 | 正常更新 | ✅ pass |
| TC-0121 | 不存在 | ✅ pass |
| TC-0122 | 正常查询 | ✅ pass |
| TC-0123 | pageSize超过上限 | ✅ pass |
| TC-0124 | 正常查询 | ✅ pass |
| TC-0125 | 不存在 | ✅ pass |
| TC-0730 | 非超管 admin 把 roleA.PermsLevel 从 100 调到 10(数字变小 = 提升权级) | ✅ pass |
| TC-0731 | 产品 admin 保持或提升 PermsLevel | ✅ pass |
| TC-0732 | 超管降低 PermsLevel | ✅ pass |
| TC-0733 | PermsLevel 越界(0/-1/1000/10000) | ✅ pass |
| TC-0777 | UpdateRole:UpdateWithOptLock 成功,FindUserIdsByRoleId 失败,handler 返回 nil(降级成功) | ✅ pass |
| TC-0778 | UpdateRole 乐观锁冲突 | ✅ pass |
| TC-0779 | UpdateProduct 乐观锁冲突 | ✅ pass |
| TC-0780 | UpdateMember 基于事务内 locked 数据更新 | ✅ pass |
| TC-0858 | BindRolePerms:事务 OK,FindUserIdsByRoleId 返回 err |
✅ pass |
| TC-0859 | UpdateRole:事务 OK,FindUserIdsByRoleId 返回 err |
✅ pass |
| TC-1000 | 非超管访问别的产品的 role | ✅ pass |
| TC-1001 | "id 不存在" vs "跨产品" 响应对比 | ✅ pass |
| TC-1002 | 超管跨产品访问 | ✅ pass |
| TC-1119 | L-R14-1:非超管 UpdateRole 别产品 roleId 必须 404 "角色不存在" | ✅ pass |
| TC-1197 | 非超管 product ADMIN 不得创建 PermsLevel=1 顶格角色(H-R17-3) |
✅ pass |
| TC-1198 | 非超管 product ADMIN 可创建 PermsLevel>=2 角色(正向回归) |
✅ pass |
| TC-1199 | SuperAdmin 仍可创建 PermsLevel=1 顶格角色(正向回归) |
✅ pass |
| TC-1204 | UpdateRole rename 后旧 name 索引缓存必须被 InvalidateRoleCache(prevName) 显式清除(H-R18-1) | ✅ pass |
POST /api/role/delete| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0126 | 正常删除+级联 | ✅ pass |
| TC-0127 | 事务回滚 | ✅ pass |
| TC-0128 | 无关联数据 | ✅ pass |
| TC-1120 | L-R14-1:非超管 DeleteRole 别产品 roleId 必须 404 "角色不存在" | ✅ pass |
| TC-1201 | DeleteRole 成功提交后必须 post-commit 同时失效 sysRole:id 与 sysRole:productCode:name 两把缓存(H-R17-2) |
✅ pass |
POST /api/role/bindPerms| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0129 | 正常绑定 | ✅ pass |
| TC-0130 | 角色不存在 | ✅ pass |
| TC-0131 | 清空权限 | ✅ pass |
| TC-0132 | 重复permId | ✅ pass |
| TC-0133 | 事务回滚 | ✅ pass |
| TC-1024 | BindRolePerms 事务首步调用 LockByIdTx 锁 sys_role 行,再走 FindPermIdsByRoleIdTx 读 diff 基准 |
✅ pass |
| TC-1025 | BindRolePerms post-commit cache 清理失败仍 Success |
✅ pass |
| TC-1026 | BindRoles 事务首步 FindOneForUpdateTx(memberId) 锁 sys_product_member 行,再走 FindRoleIdsByUserIdForProductTx |
✅ pass |
| TC-1121 | L-R14-1:非超管 BindRolePerms 别产品 roleId 必须 404 "角色不存在" | ✅ pass |
POST /api/user/create| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0134 | 正常创建 | ✅ pass |
| TC-0135 | 用户名已存在(预检) | ✅ pass |
| TC-0136 | 带完整可选字段 | ✅ pass |
| TC-0137 | 非法email格式 | ✅ pass |
| TC-0138 | 合法email | ✅ pass |
| TC-0139 | email为空(可选) | ✅ pass |
| TC-0140 | 非法phone格式 | ✅ pass |
| TC-0141 | 合法phone(国际) | ✅ pass |
| TC-0142 | phone为空(可选) | ✅ pass |
| TC-0143 | 并发同username(TOCTOU) | ✅ pass |
| TC-0144 | 唯一索引冲突消息 | ✅ pass |
| TC-0150 | 用户名含特殊字符被拒绝 | ✅ pass |
| TC-0151 | 用户名太短(1字符)被拒绝 | ✅ pass |
| TC-0152 | 用户名太长(65字符)被拒绝 | ✅ pass |
| TC-0153 | 部门不存在被拒绝 | ✅ pass |
| TC-0154 | 昵称超过64字符被拒绝 | ✅ pass |
| TC-0155 | 备注超过255字符被拒绝 | ✅ pass |
| TC-0818 | SuperAdmin 创建用户未显式指定 mustChangePassword |
✅ pass |
| TC-0994 | 产品 ADMIN 为非自己管辖部门创建用户 | ✅ pass |
| TC-0995 | 产品 ADMIN 在自己子树下创建用户 | ✅ pass |
| TC-0996 | SuperAdmin 在任意部门 / DeptId=0 均可创建 | ✅ pass |
| TC-0997 | caller.DeptPath=="" 的 legacy 产品 ADMIN | ✅ pass |
| TC-0998 | 非超管 caller 传 DeptId=0 | ✅ pass |
| TC-0999 | 目标部门 status=Disabled | ✅ pass |
| TC-1100 | 负值 DeptId(-1 / MinInt64)必须 400 | ✅ pass |
| TC-1122 | H-R14-1:非超管把新用户建到 DEV 部门必须 403 | ✅ pass |
| TC-1123 | H-R14-1:SuperAdmin 可在 DEV 部门建用户(正向回归) | ✅ pass |
| TC-1192 | 非超管以保留前缀(admin_ / svc_ / root_ / sys_)占名必须 400(L-R17-1) |
✅ pass |
| TC-1193 | SuperAdmin 以保留前缀创建用户放行(正向回归) | ✅ pass |
| TC-1194 | 未传 avatar 时 sys_user.avatar 列在 DB 层必须为 SQL NULL(L-R17-2) |
✅ pass |
| TC-1195 | mock 断言 InsertWithTx 在 TransactCtx 闭包内且顺序 FindOneForShareTx(dept) → InsertWithTx(user)(H-R17-1) |
✅ pass |
| TC-1196 | mock 断言 FindOneForShareTx 返 sqlx.ErrNotFound(并发 DeleteDept 胜出)时必须 400 "部门不存在或已删除",InsertWithTx 绝不得被调用(H-R17-1) |
✅ pass |
| TC-1280 | 正常创建用户返回 ticket(无 Password 字段) | ✅ pass |
| TC-1282 | 生成密码满足强度要求 | ✅ pass |
| TC-1284 | 创建后 mustChangePassword=1 | ✅ pass |
POST /api/user/resetPassword| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-1285 | 超管重置普通用户密码 | ✅ pass |
| TC-1287 | 不能重置超管密码 | ✅ pass |
| TC-1288 | MEMBER 无权重置 | ✅ pass |
| TC-1289 | 重置后旧 token 失效(tokenVersion 递增) | ✅ pass |
| TC-1290 | 重置后 mustChangePassword=1 | ✅ pass |
| TC-1291 | 目标用户不存在 | ✅ pass |
| TC-1293 | 重置后用新密码可验证 | ✅ pass |
POST /api/user/fetchCredentials| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-1294 | 正常消费 ticket | ✅ pass |
| TC-1295 | 二次消费同一 ticket | ✅ pass |
| TC-1296 | 空 ticket | ✅ pass |
| TC-1297 | 非法 ticket | ✅ pass |
| TC-1298 | 非 ADMIN 无权消费 | ✅ pass |
| TC-1299 | 并发消费同一 ticket 原子性 | ✅ pass |
POST /api/user/update (指针类型+DeptId可清零)| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0156 | 正常更新 | ✅ pass |
| TC-0157 | 不存在 | ✅ pass |
| TC-0158 | 仅传id | ✅ pass |
| TC-0159 | 清空nickname | ✅ pass |
| TC-0160 | 清空email | ✅ pass |
| TC-0161 | 清空remark | ✅ pass |
| TC-0162 | 非法email格式 | ✅ pass |
| TC-0163 | 非法phone格式 | ✅ pass |
| TC-0164 | 合法phone | ✅ pass |
| TC-0165 | 不传email(nil) | ✅ pass |
| TC-0166 | DeptId设为0(取消部门) | ✅ pass |
| TC-0167 | DeptId设为正值 | ✅ pass |
| TC-0168 | DeptId不传(nil) | ✅ pass |
| TC-0169 | 超管不能冻结另一超管 | ✅ pass |
| TC-0170 | updateUser-产品管理员可管理范围内用户 | ✅ pass |
| TC-0171 | updateUser-昵称超长拒绝 | ✅ pass |
| TC-0172 | updateUser-部门不存在 | ✅ pass |
| TC-0173 | updateUser 修改状态时递增 tokenVersion | ✅ pass |
| TC-0174 | updateUser 仅改 profile 不递增 tokenVersion | ✅ pass |
| TC-0175 | updateUser 乐观锁冲突 -> 409 | ✅ pass |
| TC-0746 | DEVELOPER 把成员挪出自己子树 | ✅ pass |
| TC-0747 | DEVELOPER 在自己子树内移动成员 | ✅ pass |
| TC-0748 | 产品 ADMIN 挪目标到子树外必须 403 | ✅ pass |
| TC-0814 | DEVELOPER 将他人 deptId 置 0 | ✅ pass |
| TC-0815 | MEMBER 将他人 deptId 置 0 | ✅ pass |
| TC-0816 | 产品 ADMIN 将他人 deptId 置 0 应 403 "仅超级管理员可将用户移出部门" | ✅ pass |
| TC-0817 | SuperAdmin 将他人 deptId 置 0 | ✅ pass |
| TC-1049 | deptId 切换场景下并发 DeleteDept 被"S 锁 / X 锁"串行化 | ✅ pass |
| TC-1050 | 非事务路径:deptId 未变的 UpdateUser 不触发 FindOneForShareTx 的 S 锁路径 |
✅ pass |
| TC-1101 | 负值 *req.DeptId(-1 / MinInt64)必须 400 且不得落盘 |
✅ pass |
| TC-1124 | H-R14-1:ADMIN 调入 DEV 部门必须 403 | ✅ pass |
| TC-1125 | H-R14-1:SuperAdmin 仍可调入 DEV 部门(正向回归) | ✅ pass |
| TC-1126 | 产品 ADMIN 在自己子树内挪目标(非 DEV)放行 | ✅ pass |
| TC-1170 | 跨产品 P1 ADMIN 不得把共有 target 挪到 P1 子树之外 | ✅ pass |
| TC-1171 | target 从 DEV+Enabled 部门 → NORMAL 部门:tokenVersion +1 | ✅ pass |
| TC-1172 | target 从 DEV+Enabled 部门 → deptId=0:tokenVersion +1 | ✅ pass |
| TC-1173 | NORMAL→NORMAL 不递增 tokenVersion(正向回归) | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0176 | 含productCode | ✅ pass |
| TC-0177 | 不含productCode | ✅ pass |
| TC-0178 | pageSize超过上限 | ✅ pass |
| TC-0179 | 用户不在产品中 | ✅ pass |
| TC-0180 | 批量查询DB异常 | ✅ pass |
| TC-1267 | userDetail 超管不传 productCode → roleIds 含全量角色(跨产品) | ✅ pass |
| TC-1268 | userDetail 超管传 productCode → roleIds 只含该产品角色 | ✅ pass |
| TC-0182 | 正常查询-含Avatar | ✅ pass |
| TC-0183 | 不存在 | ✅ pass |
| TC-1269 | userDetail 非超管不传 productCode → roleIds 只含 JWT context 产品角色 | ✅ pass |
| TC-0184 | 正常绑定 | ✅ pass |
| TC-0185 | 用户不存在 | ✅ pass |
| TC-0186 | 清空角色 | ✅ pass |
| TC-0187 | 事务回滚 | ✅ pass |
| TC-0188 | 角色不属于当前产品 | ✅ pass |
| TC-0189 | 角色已禁用 | ✅ pass |
| TC-0190 | 角色不存在 | ✅ pass |
| TC-0191 | 非产品成员绑定角色被拒绝 | ✅ pass |
| TC-0192 | 正常ALLOW | ✅ pass |
| TC-0193 | 用户不存在 | ✅ pass |
| TC-0194 | DENY权限 | ✅ pass |
| TC-0195 | 清空权限 | ✅ pass |
| TC-0196 | 无效Effect值 | ✅ pass |
| TC-0197 | PermId不存在 | ✅ pass |
| TC-0198 | 权限不属于当前产品 | ✅ pass |
| TC-0199 | 非产品成员设置权限被拒绝 | ✅ pass |
| TC-0200 | 正常冻结 + tokenVersion +1(会话立即失效) |
✅ pass |
| TC-0201 | 正常解冻 + tokenVersion +1(L-R17-6:无条件吊销,堵"UD 缓存残留→旧 token 复活") |
✅ pass |
| TC-0202 | 非法status(0) | ✅ pass |
| TC-0203 | 冻结自己 | ✅ pass |
| TC-0204 | 冻结超管 | ✅ pass |
| TC-0205 | userList-非超管仅可见产品成员 | ✅ pass |
| TC-0206 | userList-非超管未指定productCode被拒绝 | ✅ pass |
| TC-0207 | userList-非超管使用错误productCode被拒绝 | ✅ pass |
| TC-0208 | bindRoles-permsLevel越权拒绝 | ✅ pass |
| TC-0209 | bindRoles-超管可分配任意级别角色 | ✅ pass |
| TC-0210 | 同一权限ID冲突Effect被拒绝 | ✅ pass |
| TC-0211 | 重复权限ID相同Effect去重 | ✅ pass |
| TC-0212 | 已禁用权限不能被设置 | ✅ pass |
| TC-0711 | ADMIN 调用者豁免 permsLevel 校验 | ✅ pass |
| TC-0712 | DEVELOPER 调用者豁免 permsLevel 校验 | ✅ pass |
| TC-0713 | MinPermsLevel=MaxInt64 的 MEMBER 不被误阻断 | ✅ pass |
| TC-0734 | 产品已禁用 | ✅ pass |
| TC-0735 | 产品不存在 | ✅ pass |
| TC-0743 | 普通 MEMBER 给自己授权 | ✅ pass |
| TC-0744 | DEVELOPER 调用者(非 ADMIN)操作他人 | ✅ pass |
| TC-0745 | 同产品 ADMIN 操作合法 MEMBER 目标 | ✅ pass |
| TC-0772 | 状态无实际变化(已启用→再启用) | ✅ pass |
| TC-0773 | 状态实际变化(启用→冻结) | ✅ pass |
| TC-0786 | SetUserPerms 调用后 req.Perms 不变 | ✅ pass |
| TC-0787 | BindRoles 调用后 req.RoleIds 不变 | ✅ pass |
| TC-0788 | BindRolePerms 调用后 req.PermIds 不变 | ✅ pass |
| TC-0813 | MEMBER 调用者给他人赋予 "与自己 permsLevel 相同" 的角色 | ✅ pass |
| TC-0988 | FindByIds 前置校验通过(装饰器撒谎 status=1)但 DB 实际 status=2 | ✅ pass |
| TC-0989 | 全部真实 Enabled 的正向基线 | ✅ pass |
| TC-0991 | 自看原样返回 Email/Phone/Remark(业务契约回归守卫) | ✅ pass |
| TC-0992 | SuperAdmin 看任何人原样返回 Email/Phone/Remark(业务契约回归守卫) | ✅ pass |
| TC-1011 | 他人先冻结后本轮解冻 | ✅ pass |
| TC-1012 | Logic 层错误映射 | ✅ pass |
| TC-1027 | 登录时用户在 productCode 下非成员 |
✅ pass |
| TC-1028 | 登录时用户成员资格 Status=Disabled |
✅ pass |
| TC-1078 | BindRoles 与 DeleteRole 并发 6 轮(统一文案为"包含无效的角色ID"后稳定) | ✅ pass |
| TC-1102 | BindRoles 非超管 + 空 MemberType + 不存在 userId → 403 "缺少产品成员上下文" | ✅ pass |
| TC-1103 | BindRoles 超管不传 productCode → 400 "必须指定产品编码"(前置校验) | ✅ pass |
| TC-1265 | BindRoles 非超管传入 req.ProductCode 指向其他产品 → 字段被忽略,仍按 JWT context 产品操作 | ✅ pass |
| TC-1266 | BindRoles 非超管不传 req.ProductCode → 使用 JWT context productCode 正常绑定 | ✅ pass |
| TC-1104 | SetUserPerms 非 ADMIN caller + 不存在 userId → 403(阻断 userId 枚举) | ✅ pass |
| TC-1105 | SetUserPerms DENY TOCTOU:事务内读到 ADMIN → 400 + 事务回滚(无 DENY 脏行) | ✅ pass |
| TC-1106 | SetUserPerms 纯 ALLOW 必须短路、不调 FindOneForShareTx(S 锁开销不扩散) | ✅ pass |
| TC-1127 | L-R14-2:BindRoles 跨产品 / 已禁用 / 不存在三路径文案必须统一为"包含无效的角色ID" | ✅ pass |
| TC-1164 | 产品 ADMIN 看同产品他人 UserDetail:返回完整 Email/Phone/Remark | ✅ pass |
| TC-1165 | 产品 DEVELOPER 看同产品他人 UserDetail:返回完整 Email/Phone/Remark | ✅ pass |
| TC-1166 | 产品 MEMBER 看同产品他人 UserDetail:Email/Phone/Remark 必须为空字符串 | ✅ pass |
| TC-1167 | 产品 ADMIN 列表视角:全部成员 PII 原值返回 | ✅ pass |
| TC-1168 | 产品 DEVELOPER 列表视角:全部成员 PII 原值返回 | ✅ pass |
| TC-1169 | 产品 MEMBER 列表视角:其他成员 Email/Phone/Remark 必须为空字符串 | ✅ pass |
POST /api/user/userPerms| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-1257 | 超管查任意用户权限覆盖 | ✅ pass |
| TC-1258 | 用户查询自己的权限覆盖(ALLOW + DENY 各 1 条) | ✅ pass |
| TC-1259 | 产品 ADMIN 查同产品 MEMBER 的权限覆盖 | ✅ pass |
| TC-1260 | 产品 ADMIN 查同级 ADMIN 被拒绝(等级校验) | ✅ pass |
| TC-1261 | 普通 MEMBER 查他人被拒绝(RequireProductAdminFor 前置) | ✅ pass |
| TC-1262 | 非 ADMIN 查不存在 userId 必须 403(枚举防护) | ✅ pass |
| TC-1263 | ADMIN 查不是当前产品成员的用户被拒绝 | ✅ pass |
| TC-1264 | nil UserDetails(模拟无 JWT)返回 401 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0213 | 正常添加 | ✅ pass |
| TC-0214 | 产品不存在 | ✅ pass |
| TC-0215 | 用户不存在 | ✅ pass |
| TC-0216 | 已是成员 | ✅ pass |
| TC-0217 | 并发添加 | ✅ pass |
| TC-0218 | 无效MemberType | ✅ pass |
| TC-0219 | 正常更新 | ✅ pass |
| TC-0220 | 不存在 | ✅ pass |
| TC-0221 | 无效MemberType | ✅ pass |
| TC-0222 | 正常查询(批量查用户) | ✅ pass |
| TC-0223 | 成员用户已删除 | ✅ pass |
| TC-0224 | pageSize超过上限 | ✅ pass |
| TC-0225 | 空成员列表 | ✅ pass |
| TC-0226 | 正常移除+级联(事务内) | ✅ pass |
| TC-0227 | 跨产品隔离 | ✅ pass |
| TC-0228 | 成员不存在 | ✅ pass |
| TC-0229 | 事务回滚 | ✅ pass |
| TC-0723 | 移除产品唯一 ADMIN | ✅ pass |
| TC-0724 | 有 2 个 ADMIN 时移除其一 | ✅ pass |
| TC-0725 | 降级产品唯一 ADMIN 为 MEMBER | ✅ pass |
| TC-0726 | 有 2 个 ADMIN 时降级其一 | ✅ pass |
| TC-0727 | 2 个 ADMIN 但只有 1 个启用,降级该启用 ADMIN | ✅ pass |
| TC-0728 | 移除非 ADMIN(MEMBER) | ✅ pass |
| TC-0729 | 对禁用产品 addMember | ✅ pass |
| TC-0760 | 保持 memberType=ADMIN 但 status 改为 Disabled | ✅ pass |
| TC-0761 | 同时降级 + 禁用唯一 ADMIN | ✅ pass |
| TC-0762 | 有 2 个 ADMIN 时禁用其一 | ✅ pass |
| TC-0763 | 移除活跃 ADMIN(事务内用 locked 数据判断) | ✅ pass |
| TC-0764 | 移除非 ADMIN 不触发 last-admin 校验 | ✅ pass |
| TC-0789 | caller.MemberType="" 调用 CheckMemberTypeAssignment | ✅ pass |
| TC-0940 | Product ADMIN 拉跨部门树的人 | ✅ pass |
| TC-0941 | Product ADMIN 在自己部门树内 | ✅ pass |
| TC-0942 | SuperAdmin 跨一切部门 | ✅ pass |
| TC-0943 | 自己加自己 | ✅ pass |
| TC-0944 | caller 没有部门(DeptId=0 或 DeptPath="") | ✅ pass |
| TC-0945 | target 无部门(DeptId=0) | ✅ pass |
| TC-0946 | ctx 无 caller | ✅ pass |
| TC-0947 | dept.FindOne 报错 | ✅ pass |
| TC-0948 | target 为 nil | ✅ pass |
| TC-0949 | AddMember 集成:跨部门被拒 | ✅ pass |
| TC-0950 | AddMember 集成:target=SuperAdmin | ✅ pass |
| TC-1055 | MemberType==nil && Status==nil → 400 "请至少提供一个要更新的字段" |
✅ pass |
| TC-1056 | 只传 Status,MemberType 保持不变 |
✅ pass |
| TC-1057 | 只传 MemberType,Status 保持不变 |
✅ pass |
| TC-1058 | DEVELOPER → 只改 Status 时跳过"分配校验" | ✅ pass |
| TC-1059 | 非法 Status 值(例如 7)→ 400 | ✅ pass |
| TC-1060 | 完全 no-op(传进来的值与 DB 现值相同)→ 返 nil 且 updateTime 不前进 | ✅ pass |
| TC-1107 | addMember 非 ADMIN caller + 不存在 productCode → 403(阻断 productCode 枚举) | ✅ pass |
| TC-1108 | addMember 非 ADMIN caller + 非法 MemberType → 403(权限优先于字面校验) | ✅ pass |
| TC-1109 | addMember 超管 + 非法 MemberType → 400(正向回归,权限闸没误伤字面 400) | ✅ pass |
| TC-1130 | 降级 ADMIN→MEMBER 同事务递增 sys_user.tokenVersion | ✅ pass |
| TC-1131 | 禁用启用成员(Status 1→2)时 tokenVersion+1 | ✅ pass |
| TC-1132 | 降级 DEVELOPER→MEMBER 时 tokenVersion+1(privileged 并集) | ✅ pass |
| TC-1133 | 升权 MEMBER→ADMIN 不 递增 tokenVersion | ✅ pass |
| TC-1134 | 重启用(Disabled→Enabled)tokenVersion 不变 | ✅ pass |
| TC-1135 | 降级最后一个 ADMIN 被拒时 tokenVersion 未被污染(事务 rollback 原子性) | ✅ pass |
| TC-1136 | no-op 更新(与现值一致)不进入事务,tokenVersion 不变 | ✅ pass |
| TC-1137 | 降级后 post-commit 失效 sysUser id/username 两把低层缓存 | ✅ pass |
| TC-1162 | 移除成员后被移除用户 sys_user.tokenVersion 必须 +1 | ✅ pass |
| TC-1163 | 移除失败(last-admin 场景)时 tokenVersion 绝不得 +1 | ✅ pass |
| TC-1270 | userProducts 超管查询他人产品列表(集成) | ✅ pass |
| TC-1271 | userProducts 本人查询自己的产品列表(集成) | ✅ pass |
| TC-1272 | userProducts 非超管查询他人 → 403(集成) | ✅ pass |
| TC-1273 | userProducts 用户未加入任何产品 → 空列表(集成) | ✅ pass |
| TC-1274 | userProducts 超管查询多产品(mock) | ✅ pass |
| TC-1275 | userProducts 本人查询自己(mock) | ✅ pass |
| TC-1276 | userProducts 非超管查他人 → 403(mock) | ✅ pass |
| TC-1277 | userProducts DB 错误透传(mock) | ✅ pass |
| TC-1278 | userProducts 产品查询失败跳过(mock) | ✅ pass |
| TC-1279 | userProducts 空列表(mock) | ✅ pass |
POST /api/captcha/get| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-1208 | 正常获取(默认宽高) | ✅ pass |
| TC-1209 | 自定义宽高 | ✅ pass |
| TC-1210 | 宽高为 0 或负数,退化为默认值 | ✅ pass |
| TC-1252 | VerifyCaptcha 正确码消费后不可重用 | ✅ pass |
| TC-1253 | VerifyCaptcha 错误码不消费 | ✅ pass |
| TC-1254 | VerifyCaptcha 不存在的 id | ✅ pass |
POST /api/capjs/endpoint| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-1211 | cap.js 已启用 | ✅ pass |
| TC-1212 | cap.js 未启用 | ✅ pass |
| TC-1255 | cap.js 启用但 EndpointURL 为空 | ✅ pass |
| TC-1256 | cap.js 启用但 Key 为空 | ✅ pass |
POST /api/auth/login/cap| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-1219 | cap.js 未启用时调用 | ✅ pass |
| TC-1220 | capToken 为空 | ✅ pass |
| TC-1221 | capToken 无效(远端校验失败) | ✅ pass |
| TC-1222 | capToken 有效 + 正常登录 | ✅ pass |
| TC-1223 | capToken 有效 + 密码错误 | ✅ pass |
| TC-1224 | capToken 有效 + 超管被拒绝 | ✅ pass |
POST /api/auth/adminLogin/cap| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-1225 | cap.js 未启用时调用 | ✅ pass |
| TC-1226 | capToken 为空 | ✅ pass |
| TC-1227 | capToken 有效 + managementKey 无效 | ✅ pass |
| TC-1228 | capToken 有效 + 超管正常登录 | ✅ pass |
| TC-1229 | capToken 有效 + 非超管被拒绝 | ✅ pass |
POST /api/auth/updateInfo| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-1230 | 未登录 | ✅ pass |
| TC-1231 | 所有字段为 nil | ✅ pass |
| TC-1232 | 正常更新 nickname | ✅ pass |
| TC-1233 | 正常更新 avatar | ✅ pass |
| TC-1234 | 正常更新 email + phone | ✅ pass |
| TC-1235 | nickname 超过 64 字符 | ✅ pass |
| TC-1236 | avatar 超过 255 字符 | ✅ pass |
| TC-1237 | email 超过 64 字符 | ✅ pass |
| TC-1238 | phone 超过 32 字符 | ✅ pass |
| TC-1239 | 并发更新冲突 | ✅ pass |
| TC-1240 | 更新后 UserDetails 缓存失效 | ✅ pass |
POST /api/minio/upload| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-1242 | fileType 为空 | ✅ pass |
| TC-1243 | fileType 不在配置中 | ✅ pass |
| TC-1244 | Content-Type 不在白名单中 | ✅ pass |
| TC-1248 | parseDir 模板替换 {yyyy}/{mm}/{dd} | ✅ pass |
| TC-1249 | handler 缺少 file 字段 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0230 | 正常同步 | ✅ pass |
| TC-0231 | appKey无效 | ✅ pass |
| TC-0232 | appSecret错误 | ✅ pass |
| TC-0233 | 产品已禁用 | ✅ pass |
| TC-0234 | 验证disabled计数 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0235 | 正常登录(普通用户+productCode) | ✅ pass |
| TC-0236 | 用户不存在 | ✅ pass |
| TC-0237 | 密码错误 | ✅ pass |
| TC-0238 | 账号冻结 | ✅ pass |
| TC-0239 | 超管被拒绝 | ✅ pass |
| TC-0240 | 普通用户+productCode | ✅ pass |
| TC-0241 | 产品成员被禁用时拒绝登录 | ✅ pass |
| TC-0242 | productCode为空 | ✅ pass |
| TC-0243 | 正常刷新 | ✅ pass |
| TC-0244 | token无效 | ✅ pass |
| TC-0245 | 账号冻结 | ✅ pass |
| TC-0246 | productCode回退到claims | ✅ pass |
| TC-0247 | 超管+productCode | ✅ pass |
| TC-0248 | 普通用户+productCode | ✅ pass |
| TC-0249 | 有效token | ✅ pass |
| TC-0250 | 无效token | ✅ pass |
| TC-0251 | 缺少userId | ✅ pass |
| TC-0252 | 冻结用户token返回Invalid | ✅ pass |
| TC-0253 | 非成员token返回Invalid | ✅ pass |
| TC-0254 | 返回实时MemberType和Perms | ✅ pass |
| TC-0255 | 用户不存在(需先通过AppKey/Secret认证) | ✅ pass |
| TC-0256 | 超管(需先通过AppKey/Secret认证) | ✅ pass |
| TC-0257 | MEMBER-DENY覆盖(需先通过AppKey/Secret认证) | ✅ pass |
| TC-0700 | 冻结用户 (Status=Disabled) | ✅ pass |
| TC-0701 | 非产品成员 | ✅ pass |
| TC-0702 | DEV 部门但产品成员被禁用 | ✅ pass |
| TC-0703 | 启用 ADMIN 成员(正向回归) | ✅ pass |
| TC-0704 | Loader 层:DEV 部门 + 产品成员禁用 | ✅ pass |
| TC-0782 | VerifyToken 各失败分支记录日志 | ✅ pass |
| TC-0783 | peer.FromContext 失败时仍限流 | ✅ pass |
| TC-0794 | VerifyToken 对任意畸形 AccessToken | ✅ pass |
| TC-0795 | GetUserPerms 任意 (appKey,appSecret,productCode,userId) | ✅ pass |
| TC-0828 | 同 IP 两次 gRPC RefreshToken,quota=1 | ✅ pass |
| TC-0829 | 同 IP 两次 gRPC VerifyToken,quota=1 | ✅ pass |
| TC-0830 | extractClientIP 对 "host:port" 剥离 |
✅ pass |
| TC-0831 | gRPC refresh 成功后重放旧 rt(换端口) | ✅ pass |
| TC-1036 | GetUserPerms 查询 userId 全局不存在 |
✅ pass |
| TC-1037 | GetUserPerms 查询 userId 存在但非成员 |
✅ pass |
| TC-1038 | GetUserPerms 查询成员 Status=Disabled |
✅ pass |
| TC-1051 | SyncPermissions 同 appKey 连打 quota+1 次触发 ResourceExhausted |
✅ pass |
| TC-1052 | GetUserPerms 同 appKey 连打 quota+1 次触发 ResourceExhausted |
✅ pass |
| TC-1053 | 空 AppKey 不消耗 limiter 配额 |
✅ pass |
| TC-1054 | GetUserPerms 同一 IP、多个不同 appKey → 命中 IP 桶 |
✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0258 | 正常Bearer token | ✅ pass |
| TC-0259 | 无Authorization头 | ✅ pass |
| TC-0260 | 无Bearer前缀 | ✅ pass |
| TC-0261 | token签名错误 | ✅ pass |
| TC-0262 | token过期 | ✅ pass |
| TC-0263 | claims类型断言失败 | ⏭️ skip |
| TC-0264 | refresh token被拒绝 | ✅ pass |
| TC-0265 | 业务错误(CodeError) | ✅ pass |
| TC-0266 | 内部错误 | ✅ pass |
| TC-0267 | 成功(有data) | ✅ pass |
| TC-0268 | 成功(无data) | ✅ pass |
| TC-0716 | access token payload 中不得含 perms | ✅ pass |
| TC-0749 | token.tokenVersion != DB & 产品被禁用 | ✅ pass |
| TC-0750 | token.tokenVersion == DB,产品被禁用 | ✅ pass |
| TC-0754 | 用户已被删除 + TokenVersion 失配 | ✅ pass |
| TC-0755 | 账号冻结 + TokenVersion 失配 + 产品禁用 | ✅ pass |
| TC-0756 | TokenVersion OK + 产品启用 + 非超管 + MemberType="" | ✅ pass |
| TC-0757 | SuperAdmin + ProductCode + MemberType="" | ✅ pass |
| TC-0758 | Frozen 用户 + TokenVersion 失配(无 ProductCode) | ✅ pass |
| TC-0951 | 合法 HS256 + 正确 secret | ✅ pass |
| TC-0952 | alg=none 伪造 | ✅ pass |
| TC-0953 | alg=RS256 但用 HS secret 签名 | ✅ pass |
| TC-0954 | alg=ES256 header | ✅ pass |
| TC-0955 | HS256 但 secret 错 | ✅ pass |
| TC-0956 | ParseRefreshToken 复用 ParseWithHMAC | ✅ pass |
| TC-0957 | 乱码 token | ✅ pass |
| TC-0958 | ParseRefreshToken 的 tokenType 校验 | ✅ pass |
| TC-0959 | 合法 HS256 + 非标 typ header |
✅ pass |
| TC-0960 | 回放过期 token | ✅ pass |
| TC-1003 | 合法 HS256 token | ✅ pass |
| TC-1004 | alg=RS256(公钥→HMAC 混淆)伪造 | ✅ pass |
| TC-1005 | alg=none 伪造 | ✅ pass |
| TC-1006 | HS256 但错误 secret | ✅ pass |
| TC-1007 | 任意 jwt.Claims 结构体 |
✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0269 | 正常值 | ✅ pass |
| TC-0270 | page<=0 | ✅ pass |
| TC-0271 | page=-1 | ✅ pass |
| TC-0272 | pageSize<=0 | ✅ pass |
| TC-0273 | pageSize>100 | ✅ pass |
| TC-0274 | pageSize=100 | ✅ pass |
| TC-0275 | pageSize=101 | ✅ pass |
| TC-0276 | 双零 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0277 | 正常邮箱 | ✅ pass |
| TC-0278 | 含点号 | ✅ pass |
| TC-0279 | 含加号 | ✅ pass |
| TC-0280 | 缺少@ | ✅ pass |
| TC-0281 | 缺少域名 | ✅ pass |
| TC-0282 | 缺少TLD | ✅ pass |
| TC-0283 | 空字符串 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0284 | 国内手机号 | ✅ pass |
| TC-0285 | 带+国际码 | ✅ pass |
| TC-0286 | 太短(6位) | ✅ pass |
| TC-0287 | 恰好7位 | ✅ pass |
| TC-0288 | 最长15位 | ✅ pass |
| TC-0289 | 超长16位 | ✅ pass |
| TC-0290 | 包含字母 | ✅ pass |
| TC-0291 | 空字符串 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0292 | 正常生成 | ✅ pass |
| TC-0293 | 解析token验证claims | ✅ pass |
| TC-0294 | 空secret | ✅ pass |
| TC-0295 | 空perms | ✅ pass |
| TC-0296 | 过期时间验证 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0297 | 正常生成 | ✅ pass |
| TC-0298 | 解析验证 | ✅ pass |
| TC-0299 | productCode为空 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0300 | 正常解析 | ✅ pass |
| TC-0301 | 错误secret | ✅ pass |
| TC-0302 | 无效token字符串 | ✅ pass |
| TC-0303 | 空token | ✅ pass |
| TC-0304 | 过期token | ✅ pass |
| TC-0305 | AccessToken误用 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0306 | GetUserId-正常 | ✅ pass |
| TC-0307 | GetUserId-空ctx | ✅ pass |
| TC-0308 | GetProductCode-正常 | ✅ pass |
| TC-0309 | GetUserDetails 返回完整字段 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0310 | Insert — 正常插入 | ✅ pass |
| TC-0311 | Insert — 正常插入含TokenVersion | ✅ pass |
| TC-0312 | Insert — 唯一索引冲突 | ✅ pass |
| TC-0313 | Insert — 缓存key生成正确 | ✅ pass |
| TC-0314 | InsertWithTx — 事务内插入 | ✅ pass |
| TC-0315 | InsertWithTx — 事务内插入含TokenVersion | ✅ pass |
| TC-0316 | InsertWithTx — 事务回滚后无数据 | ✅ pass |
| TC-0317 | FindOne — 正常查询(缓存未命中) | ✅ pass |
| TC-0318 | FindOne — 正常查询(缓存命中) | ✅ pass |
| TC-0319 | FindOne — 记录不存在 | ✅ pass |
| TC-0320 | FindOne — DB异常(非ErrNotFound) | ✅ pass |
| TC-0321 | FindOneWithTx — 事务内正常查询 | ✅ pass |
| TC-0322 | FindOneWithTx — 事务内记录不存在 | ✅ pass |
| TC-0323 | FindOneWithTx — 事务内可见性 | ✅ pass |
| TC-0324 | Update — 正常更新 | ✅ pass |
| TC-0325 | Update — 正常更新含TokenVersion | ✅ pass |
| TC-0326 | Update — 记录不存在 | ✅ pass |
| TC-0327 | UpdateWithTx — 事务内更新 | ✅ pass |
| TC-0328 | Delete — 正常删除 | ✅ pass |
| TC-0329 | Delete — 记录不存在 | ✅ pass |
| TC-0330 | DeleteWithTx — 事务内删除 | ✅ pass |
| TC-0331 | TransactCtx — 正常事务 | ✅ pass |
| TC-0332 | TransactCtx — fn返回错误 | ✅ pass |
| TC-0333 | TableName — 获取表名 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0334 | BatchInsert — 空列表 | ✅ pass |
| TC-0335 | BatchInsert — 单条记录 | ✅ pass |
| TC-0336 | BatchInsert — 多条记录(3条) | ✅ pass |
| TC-0337 | BatchInsert — 批量插入含TokenVersion | ✅ pass |
| TC-0338 | BatchInsert — 唯一索引冲突 | ✅ pass |
| TC-0339 | BatchInsert — 大批量(1000条) | ✅ pass |
| TC-0340 | BatchInsertWithTx — 空列表 | ✅ pass |
| TC-0341 | BatchInsertWithTx — 正常多条 | ✅ pass |
| TC-0342 | BatchInsertWithTx — 事务回滚 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0343 | BatchUpdate — 空列表 | ✅ pass |
| TC-0344 | BatchUpdate — 单条记录 | ✅ pass |
| TC-0345 | BatchUpdate — 多条记录(3条) | ✅ pass |
| TC-0346 | BatchUpdate — 批量更新不污染数据 | ✅ pass |
| TC-0347 | BatchUpdate — 部分id不存在 | ✅ pass |
| TC-0348 | BatchUpdateWithTx — 空列表 | ✅ pass |
| TC-0349 | BatchUpdateWithTx — 正常多条 | ✅ pass |
| TC-0350 | buildBatchUpdateQuery — 单条 | ✅ pass |
| TC-0351 | buildBatchUpdateQuery — 多条 | ✅ pass |
| TC-0352 | buildBatchUpdateQuery — vals数量正确 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0353 | BatchDelete — 空ids | ✅ pass |
| TC-0354 | BatchDelete — 单个id | ✅ pass |
| TC-0355 | BatchDelete — 多个id(3个) | ✅ pass |
| TC-0356 | BatchDelete — 包含不存在id | ✅ pass |
| TC-0357 | BatchDeleteWithTx — 空ids | ✅ pass |
| TC-0358 | BatchDeleteWithTx — 正常多条 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0359 | FindOneByUsername — 正常查询 | ✅ pass |
| TC-0360 | FindOneByUsername — 不存在 | ✅ pass |
| TC-0361 | FindOneByUsernameWithTx — 事务内正常查询 | ✅ pass |
| TC-0362 | FindOneByUsernameWithTx — 事务内不存在 | ✅ pass |
| TC-0363 | FindOneByAppKey — 正常查询 | ✅ pass |
| TC-0364 | FindOneByAppKey — 不存在 | ✅ pass |
| TC-0365 | FindOneByAppKeyWithTx — 事务内正常查询 | ✅ pass |
| TC-0366 | FindOneByAppKeyWithTx — 事务内不存在 | ✅ pass |
| TC-0367 | FindOneByCode — 正常查询 | ✅ pass |
| TC-0368 | FindOneByCode — 不存在 | ✅ pass |
| TC-0369 | FindOneByCodeWithTx — 事务内正常查询 | ✅ pass |
| TC-0370 | FindOneByCodeWithTx — 事务内不存在 | ✅ pass |
| TC-0371 | FindOneByProductCodeCode — 正常查询 | ✅ pass |
| TC-0372 | FindOneByProductCodeCode — 不存在 | ✅ pass |
| TC-0373 | FindOneByProductCodeCodeWithTx — 事务内正常查询 | ✅ pass |
| TC-0374 | FindOneByProductCodeCodeWithTx — 事务内不存在 | ✅ pass |
| TC-0375 | FindOneByProductCodeName — 正常查询 | ✅ pass |
| TC-0376 | FindOneByProductCodeName — 不存在 | ✅ pass |
| TC-0377 | FindOneByProductCodeNameWithTx — 事务内正常查询 | ✅ pass |
| TC-0378 | FindOneByProductCodeNameWithTx — 事务内不存在 | ✅ pass |
| TC-0379 | FindOneByRoleIdPermId — 正常查询 | ✅ pass |
| TC-0380 | FindOneByRoleIdPermId — 不存在 | ✅ pass |
| TC-0381 | FindOneByRoleIdPermIdWithTx — 事务内正常查询 | ✅ pass |
| TC-0382 | FindOneByRoleIdPermIdWithTx — 事务内不存在 | ✅ pass |
| TC-0383 | FindOneByUserIdPermId — 正常查询 | ✅ pass |
| TC-0384 | FindOneByUserIdPermId — 不存在 | ✅ pass |
| TC-0385 | FindOneByUserIdPermIdWithTx — 事务内正常查询 | ✅ pass |
| TC-0386 | FindOneByUserIdPermIdWithTx — 事务内不存在 | ✅ pass |
| TC-0387 | FindOneByUserIdRoleId — 正常查询 | ✅ pass |
| TC-0388 | FindOneByUserIdRoleId — 不存在 | ✅ pass |
| TC-0389 | FindOneByUserIdRoleIdWithTx — 事务内正常查询 | ✅ pass |
| TC-0390 | FindOneByUserIdRoleIdWithTx — 事务内不存在 | ✅ pass |
| TC-0391 | FindOneByProductCodeUserId — 正常查询 | ✅ pass |
| TC-0392 | FindOneByProductCodeUserId — 不存在 | ✅ pass |
| TC-0393 | FindOneByProductCodeUserIdWithTx — 事务内正常查询 | ✅ pass |
| TC-0394 | FindOneByProductCodeUserIdWithTx — 事务内不存在 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0395 | findListByPrimaryKeys — 空ids | ✅ pass |
| TC-0396 | findListByPrimaryKeys — 正常ids | ✅ pass |
| TC-0397 | findListByPrimaryKeys — 部分不存在 | ✅ pass |
| TC-0398 | findListByPrimaryKeys — DB异常 | ✅ pass |
| TC-0399 | getPrimaryKeyValue — 正常 | ✅ pass |
| TC-0400 | formatPrimary — 正常 | ✅ pass |
| TC-0401 | queryPrimary — 正常 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0402 | cachePrefix为空 | ✅ pass |
| TC-0403 | cachePrefix非空 | ✅ pass |
| TC-0404 | 多唯一索引前缀(SysProduct) | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0405 | FindListByPage — 正常分页 | ✅ pass |
| TC-0406 | FindListByPage — 第二页 | ✅ pass |
| TC-0407 | FindListByPage — 空表 | ✅ pass |
| TC-0408 | FindListByPage — count查询失败 | ✅ pass |
| TC-0409 | FindListByPage — list查询失败 | ✅ pass |
| TC-0410 | FindListByProductMembers — 正常查询 | ✅ pass |
| TC-0411 | FindListByProductMembers — productCode不存在 | ✅ pass |
| TC-0412 | FindByIds — 正常批量查询 | ✅ pass |
| TC-0413 | FindByIds — 空ids | ✅ pass |
| TC-0414 | FindByIds — 部分id不存在 | ✅ pass |
| TC-0415 | FindByIds — DB异常 | ✅ pass |
| TC-0416 | FindIdsByDeptId — 有用户的部门 | ✅ pass |
| TC-0417 | FindIdsByDeptId — 无用户部门 | ✅ pass |
| TC-0418 | UpdateProfile — 状态未变-不递增tokenVersion | ✅ pass |
| TC-0419 | UpdateProfile — 状态变更-tokenVersion+1 | ✅ pass |
| TC-0420 | UpdateProfile — 乐观锁冲突 | ✅ pass |
| TC-0421 | UpdateProfile — 并发场景 | ✅ pass |
| TC-0422 | UpdateProfile — userId不存在 | ✅ pass |
| TC-0736 | SysUserModel — 单次 Increment 返回值 == DB 持久值 | ✅ pass |
| TC-0737 | SysUserModel — Increment 后缓存必须被主动清理 | ✅ pass |
| TC-0738 | SysUserModel — 10 goroutine 并发自增同一用户 | ✅ pass |
| TC-0784 | SysUserModel — MySQL 1062 错误正确识别 | ✅ pass |
| TC-0785 | SysUserModel — 非 1062 错误不误判 | ✅ pass |
| TC-0802 | SysUserModel — expected == DB.tokenVersion |
✅ pass |
| TC-0803 | SysUserModel — expected != DB.tokenVersion |
✅ pass |
| TC-0805 | SysUserModel — 8 goroutine 同时 CAS 同 expected | ✅ pass |
| TC-0806 | SysUserModel — 成功后 id-key / username-key 缓存一致性 | ✅ pass |
| TC-0812 | SysUserModel — logic 层 6 goroutine 并发 RefreshToken 同一旧 rt | ✅ pass |
| TC-0867 | SysUserModel — 透传 username 与 DB 一致 | ✅ pass |
| TC-0924 | SysUserModel — UpdatePassword:FindOne 填缓存后行被并发删除 | ✅ pass |
| TC-0925 | SysUserModel — UpdatePassword:正常写入 | ✅ pass |
| TC-0926 | SysUserModel — UpdatePassword:user 不存在 | ✅ pass |
| TC-0927 | SysUserModel — UpdateStatus:行被并发删除 | ✅ pass |
| TC-0928 | SysUserModel — UpdateStatus:正常禁用 | ✅ pass |
| TC-0929 | SysUserModel — UpdateStatus:user 不存在 | ✅ pass |
| TC-1044 | SysUserModel — UpdateStatus 用"错误 username" 调用 → Model 层仍按错误 key 清理 |
✅ pass |
| TC-1045 | SysUserModel — IncrementTokenVersion 用"错误 username" 调用 → 同上 |
✅ pass |
| TC-1046 | SysUserModel — IncrementTokenVersion 对"已被删除的行" 仍正常走 RowsAffected=0 → ErrUpdateConflict 分支 |
✅ pass |
| TC-1047 | SysUserModel — Logic 层 Logout 必须把 ud.Username 透传到 Model |
✅ pass |
| TC-1048 | SysUserModel — Logic 层 Logout 即使 ud.Username=="" 也必须透传(空串) |
✅ pass |
| TC-1079 | SysUserModel — UpdateProfileWithTx 成功后 id/username 两把 sysUser 缓存仍持旧值 |
✅ pass |
| TC-1080 | SysUserModel — InvalidateProfileCache 一次性失效 id / username 两把 key |
✅ pass |
| TC-1081 | SysUserModel — 两段式 E2E:UpdateProfileWithTx(不碰缓存) + InvalidateProfileCache(清缓存) | ✅ pass |
| TC-1082 | SysUserModel — UpdateUser tx 分支(改 deptId)post-commit 失效 sysUser 两级缓存 | ✅ pass |
| TC-1083 | SysUserModel — (保留编号) | ✅ pass |
| TC-1143 | SysUserModel — IncrementTokenVersionWithTx 事务内 UPDATE 返回 LAST_INSERT_ID(DB 真实递增值) |
✅ pass |
| TC-1144 | SysUserModel — IncrementTokenVersionWithTx 目标行被并发删除 → ErrUpdateConflict(affected=0) |
✅ pass |
| TC-1145 | SysUserModel — IncrementTokenVersionWithTx nil session → fail-fast 报错 |
✅ pass |
| TC-1146 | SysUserModel — IncrementTokenVersionWithTx 事务 rollback 时 DB 不落盘 |
✅ pass |
| TC-1147 | SysUserModel — BatchIncrementTokenVersionWithTx 多用户全部 +1 |
✅ pass |
| TC-1148 | SysUserModel — BatchIncrementTokenVersionWithTx 空 ids 不报错、不触达 DB |
✅ pass |
| TC-1149 | SysUserModel — BatchIncrementTokenVersionWithTx nil session → fail-fast 报错 |
✅ pass |
| TC-1150 | SysUserModel — BatchIncrementTokenVersionWithTx 事务 rollback 时全部回滚 |
✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0423 | FindList — 正常分页 | ✅ pass |
| TC-0424 | FindList — 空表 | ✅ pass |
| TC-0425 | FindList — count失败 | ✅ pass |
| TC-1151 | SysProductModel — UpdateWithOptLockTx 正常事务内 CAS 命中 → DB 落盘 |
✅ pass |
| TC-1152 | SysProductModel — UpdateWithOptLockTx expectedUpdateTime 错位 → ErrUpdateConflict,DB 不变 |
✅ pass |
| TC-1153 | SysProductModel — UpdateWithOptLockTx nil session → fail-fast 报错 |
✅ pass |
| TC-1154 | SysProductModel — UpdateWithOptLockTx 事务 rollback 时 DB 不落盘 |
✅ pass |
| TC-1155 | SysProductModel — InvalidateProductCache 一次性失效 id / appKey / code 三把低层缓存 |
✅ pass |
| TC-1156 | SysProductModel — InvalidateProductCache 在 canceled/deadline ctx 下不 panic、不阻塞 |
✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0426 | FindListByProductCode — 正常分页 | ✅ pass |
| TC-0427 | FindListByProductCode — 不存在的productCode | ✅ pass |
| TC-0428 | FindAllCodesByProductCode — 正常查询 | ✅ pass |
| TC-0429 | FindAllCodesByProductCode — 空结果 | ✅ pass |
| TC-0430 | FindByIds — 正常 | ✅ pass |
| TC-0431 | FindByIds — 空ids | ✅ pass |
| TC-0432 | FindMapByProductCode — 正常查询 | ✅ pass |
| TC-0433 | FindMapByProductCode — 空结果 | ✅ pass |
| TC-0434 | FindMapByProductCode — key唯一性 | ✅ pass |
| TC-0435 | DisableNotInCodesWithTx — codes非空-正常 | ✅ pass |
| TC-0436 | DisableNotInCodesWithTx — codes为空-全部禁用 | ✅ pass |
| TC-0437 | DisableNotInCodesWithTx — 无需禁用 | ✅ pass |
| TC-0438 | DisableNotInCodesWithTx — DB异常 | ✅ pass |
| TC-0439 | FindAllCodesByProductCode — 有权限产品 | ✅ pass |
| TC-0440 | FindAllCodesByProductCode — 无权限产品 | ✅ pass |
| TC-0441 | FindAllCodesByProductCode — 全部已禁用 | ✅ pass |
| TC-0986 | SysPermModel — 产品含 status ∈ {1, 2, 99} 三类行 | ✅ pass |
| TC-0987 | SysPermModel — DisableNotInCodesWithTx 只禁用 status=1 且不在白名单的行 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0442 | FindAll — 正常查询 | ✅ pass |
| TC-0443 | FindAll — 空表 | ✅ pass |
| TC-0444 | FindByParentId — 正常查询 | ✅ pass |
| TC-0445 | FindByParentId — 无子部门 | ✅ pass |
| TC-0446 | FindByPathPrefix — 正常查询 | ✅ pass |
| TC-0447 | FindByPathPrefix — LIKE注入已阻止 | ✅ pass |
| TC-0448 | FindByPathPrefix — 无匹配 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0449 | FindListByProductCode — 正常分页 | ✅ pass |
| TC-0450 | FindListByProductCode — 空结果 | ✅ pass |
| TC-0451 | FindByIds — 正常 | ✅ pass |
| TC-0452 | FindByIds — 空ids | ✅ pass |
| TC-0453 | FindMinPermsLevelByUserIdAndProductCode — 有角色用户 | ✅ pass |
| TC-0454 | FindMinPermsLevelByUserIdAndProductCode — 无角色用户 | ✅ pass |
| TC-1072 | SysRoleModel — Happy path:所有 roleId 存在且 Enabled | ✅ pass |
| TC-1073 | SysRoleModel — 存在一个被删除的 roleId | ✅ pass |
| TC-1074 | SysRoleModel — 存在一个 Disabled 的 role | ✅ pass |
| TC-1075 | SysRoleModel — 空 / nil 切片 | ✅ pass |
| TC-1076 | SysRoleModel — 入参含重复 id | ✅ pass |
| TC-1077 | SysRoleModel — 不按 productCode 过滤 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0455 | FindPermIdsByRoleId — 正常查询 | ✅ pass |
| TC-0456 | FindPermIdsByRoleId — 无绑定 | ✅ pass |
| TC-0457 | FindPermIdsByRoleIds — 正常查询 | ✅ pass |
| TC-0458 | FindPermIdsByRoleIds — 空roleIds | ✅ pass |
| TC-0459 | FindPermIdsByRoleIds — 去重验证 | ✅ pass |
| TC-0460 | DeleteByRoleIdTx — 正常事务内删除 | ✅ pass |
| TC-0461 | DeleteByRoleIdTx — 无绑定 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0462 | FindPermIdsByUserIdAndEffectForProduct — ALLOW-指定产品 | ✅ pass |
| TC-0463 | FindPermIdsByUserIdAndEffectForProduct — DENY-指定产品 | ✅ pass |
| TC-0464 | FindPermIdsByUserIdAndEffectForProduct — 无记录/其他产品 | ✅ pass |
| TC-0465 | DeleteByUserIdForProductTx — 事务内跨产品删除 | ✅ pass |
| TC-0466 | DeleteByUserIdForProductTx — 跨产品隔离 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0467 | FindRoleIdsByUserId — 正常查询 | ✅ pass |
| TC-0468 | FindRoleIdsByUserId — 无绑定 | ✅ pass |
| TC-0469 | DeleteByRoleIdTx — 正常删除 | ✅ pass |
| TC-0470 | DeleteByUserIdForProductTx — 事务内跨产品删除 | ✅ pass |
| TC-0471 | DeleteByUserIdForProductTx — 跨产品隔离 | ✅ pass |
| TC-0472 | FindUserIdsByRoleId — 有绑定的角色 | ✅ pass |
| TC-0473 | FindUserIdsByRoleId — 无绑定角色 | ✅ pass |
| TC-0474 | FindRoleIdsByUserIdForProduct — 跨产品过滤 | ✅ pass |
| TC-0706 | SysUserRoleModel — 同一产品下同时存在启用/禁用角色 | ✅ pass |
| TC-0707 | SysUserRoleModel — DeleteByUserIdAndRoleIdsTx 批量删除 | ✅ pass |
| TC-0708 | SysUserRoleModel — 批量删除空列表为 no-op | ✅ pass |
| TC-0709 | SysUserRoleModel — 批量删除仅作用于指定 userId | ✅ pass |
| TC-1061 | SysUserRoleModel — DeleteByRoleIdTx 删除多行后,id 级和组合 key 缓存全部失效 |
✅ pass |
| TC-1062 | SysUserRoleModel — DeleteByUserIdAndRoleIdsTx 只删指定 (userId, roleIds) 集合后同上 |
✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0475 | FindListByProductCode — 正常分页 | ✅ pass |
| TC-0476 | FindListByProductCode — 空结果 | ✅ pass |
| TC-0477 | FindMapByProductCodeUserIds — 正常批量 | ✅ pass |
| TC-0478 | FindMapByProductCodeUserIds — 空userIds | ✅ pass |
| TC-0479 | FindMapByProductCodeUserIds — 部分不是成员 | ✅ pass |
| TC-0480 | FindMapByProductCodeUserIds — map key正确 | ✅ pass |
| TC-0765 | SysProductMemberModel — CountActiveAdminsTx 返回正确计数 | ✅ pass |
| TC-0868 | SysProductMemberModel — 产品内 3 个 active admin,排除其中 1 | ✅ pass |
| TC-0869 | SysProductMemberModel — 唯一 active admin,排除他自己 | ✅ pass |
| TC-0870 | SysProductMemberModel — 存在 1 个 active + 1 个 disabled admin | ✅ pass |
| TC-1110 | FindOneForShareTx — 事务内读到最新行、字段对齐(S 锁契约) | ✅ pass |
| TC-1111 | FindOneForShareTx — 不存在 id 返回 sqlx.ErrNotFound(供上层区分"被并发删除") |
✅ pass |
| TC-1157 | SysProductMemberModel — FindActiveMemberUserIdsByProductCodeTx 仅返回 Enabled userId,过滤 Disabled 与其他产品 |
✅ pass |
| TC-1158 | SysProductMemberModel — FindActiveMemberUserIdsByProductCodeTx productCode 不存在时返回空切片、err=nil |
✅ pass |
| TC-1159 | SysProductMemberModel — FindActiveMemberUserIdsByProductCodeTx 仅禁用成员时返回空(status 过滤不得退化为全量) |
✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0481 | 超管通过 | ✅ pass |
| TC-0482 | 非超管拒绝 | ✅ pass |
| TC-0483 | MEMBER拒绝 | ✅ pass |
| TC-0484 | 未登录 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0485 | 超管通过 | ✅ pass |
| TC-0486 | ADMIN通过(同产品) | ✅ pass |
| TC-0487 | DEVELOPER拒绝 | ✅ pass |
| TC-0488 | MEMBER拒绝 | ✅ pass |
| TC-0489 | 未登录 | ✅ pass |
| TC-0490 | ADMIN跨产品拒绝 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0491 | 超管可分配任何类型 | ✅ pass |
| TC-0492 | ADMIN分配DEVELOPER | ✅ pass |
| TC-0493 | ADMIN分配ADMIN(同级拒绝) | ✅ pass |
| TC-0494 | DEVELOPER分配ADMIN(越级拒绝) | ✅ pass |
| TC-0495 | MEMBER分配MEMBER(同级拒绝) | ✅ pass |
| TC-0496 | 未登录 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0497 | 超管可管理任何人 | ✅ pass |
| TC-0498 | 操作自己 | ✅ pass |
| TC-0499 | ADMIN跳过部门检查 | ✅ pass |
| TC-0500 | 非ADMIN无部门拒绝 | ✅ pass |
| TC-0501 | 目标用户无部门 | ✅ pass |
| TC-0502 | 目标在不同部门 | ✅ pass |
| TC-0503 | 未登录 | ✅ pass |
| TC-0504 | caller.DeptPath为空时拒绝 | ✅ pass |
| TC-0819 | DB 层瞬时错误(mock errors.New("boom")) |
✅ pass |
| TC-0820 | DB 返回 sqlx.ErrNotFound |
✅ pass |
| TC-0860 | 传入 prefetched target,不再查 FindOne | ✅ pass |
| TC-0861 | prefetched target.Id 与参数 targetUserId 不一致 | ✅ pass |
| TC-0930 | caller 的 MinPermsLevel 缓存过期(偏高) | ✅ pass |
| TC-0931 | 同级分配 | ✅ pass |
| TC-0932 | 严格低一级分配 | ✅ pass |
| TC-0933 | SuperAdmin 绕过 DB | ✅ pass |
| TC-0934 | Product ADMIN 绕过 DB | ✅ pass |
| TC-0935 | DEVELOPER 绕过 DB | ✅ pass |
| TC-0936 | caller 在 DB 没有任何角色 | ✅ pass |
| TC-0937 | caller 查询 DB 遇到一般错误 | ✅ pass |
| TC-0938 | caller 为 nil(无 UserDetails) | ✅ pass |
| TC-0969 | caller 缓存级别高(10)但 DB 已降级(20),target 级别 15 | ✅ pass |
| TC-0970 | caller 在 DB 中无任何角色(ErrNotFound) |
✅ pass |
| TC-0971 | caller DB 级别(5)严格高于 target(15) | ✅ pass |
| TC-0972 | caller 侧 FindMinPermsLevelByUserIdAndProductCode 通用 DB 错 |
✅ pass |
| TC-0973 | caller 是 SuperAdmin | ✅ pass |
| TC-0974 | caller.UserId == targetUserId(自操作) | ✅ pass |
| TC-0975 | 共享 helper loadFreshMinPermsLevel 的契约对齐 |
✅ pass |
| TC-0993 | legacy DEVELOPER(DeptId=0、DeptPath="")去管理他人 → 403 "未归属任何部门"(与 TC-0504 合一) | ✅ pass |
| TC-1017 | SuperAdmin / ADMIN / DEVELOPER 走 HasFullPerms 短路 |
✅ pass |
| TC-1018 | MEMBER caller 仅打 1 次 DB,循环内对 5 个角色走 CheckRoleLevelAgainst 不再打 DB |
✅ pass |
| TC-1019 | caller ErrNotFound → NoRole=true,不翻 500 |
✅ pass |
| TC-1020 | caller 其他 DB 错误 → fail-close 500 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0505 | 各类型优先级正确 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0506 | DB加载(缓存miss) | ✅ pass |
| TC-0507 | 缓存命中 | ✅ pass |
| TC-0508 | 用户不存在 | ✅ pass |
| TC-0509 | productCode为空 | ✅ pass |
| TC-0705 | Load 不存在用户 | ✅ pass |
| TC-0792 | 50 goroutine barrier 同时 Load 同 userId | ✅ pass |
| TC-0793 | 首次 Load 后再 20 次 Load | ✅ pass |
| TC-0821 | 同一"不存在 userId" 第 2 次 Load | ✅ pass |
| TC-0822 | 负缓存不登记到 userIndex/productIndex |
✅ pass |
| TC-0823 | 50 并发 Load 同一不存在 userId | ✅ pass |
| TC-0913 | 用户不存在 → (ud, nil) 且 ud.Username == "" |
✅ pass |
| TC-0914 | 新建用户刚落地 CreateUser 后立刻 Load |
✅ pass |
| TC-0915 | partial load 失败(幽灵 deptId) | ✅ pass |
| TC-0916 | 全绿 MEMBER 正路径 | ✅ pass |
| TC-0917 | ErrLoaderDegraded 作为 sentinel 可 errors.Is 断言 |
✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0510 | Del删除指定缓存 | ✅ pass |
| TC-0511 | Clean清除用户所有产品缓存 | ✅ pass |
| TC-0512 | CleanByProduct清除产品所有用户 | ✅ pass |
| TC-0513 | BatchDel批量删除 | ✅ pass |
| TC-0514 | BatchDel空数组 | ✅ pass |
| TC-1013 | N=2 的真实缓存场景 | ✅ pass |
| TC-1014 | productCode="" 分支 |
✅ pass |
| TC-1112 | DetachCacheCleanCtx — parent 取消不传播到 detached ctx |
✅ pass |
| TC-1113 | DetachCacheCleanCtx — 3s 硬超时 deadline 兜底(窗口锁定) |
✅ pass |
| TC-1114 | DetachCacheCleanCtx — parent 的 Value(trace/tenant)透传 |
✅ pass |
| TC-1115 | isCtxCanceledErr — Canceled / DeadlineExceeded / wrapped 一律 true,其它 false |
✅ pass |
| TC-1116 | logCacheInvalidationErr — nil 早退、不阻塞 |
✅ pass |
| TC-1117 | logCacheInvalidationErr — ctx 取消 / 超时 / 普通错误三条分支均不 panic |
✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0515 | 超管全量权限 | ✅ pass |
| TC-0516 | ADMIN全量权限 | ✅ pass |
| TC-0517 | DEVELOPER全量权限 | ✅ pass |
| TC-0518 | DEV部门全量权限 | ✅ pass |
| TC-0519 | MEMBER角色权限+ALLOW-DENY | ✅ pass |
| TC-0520 | 用户ALLOW权限不跨产品泄漏 | ✅ pass |
| TC-0521 | 禁用DEV部门成员无全量权限 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0522 | 多角色取最小permsLevel | ✅ pass |
| TC-0523 | 无角色 | ✅ pass |
| TC-0524 | 角色跨产品过滤 | ✅ pass |
| TC-0525 | 禁用角色不计入 | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0526 | 超管自动设置SUPER_ADMIN | ✅ pass |
| TC-0527 | 非成员MemberType为空 | ✅ pass |
| TC-0528 | 禁用成员MemberType为空 | ✅ pass |
| TC-1205 | NORMAL 部门冻结(DeptStatus=Disabled)后,成员 Perms 为空 []string{}(H-R18-2) | ✅ pass |
| TC-1206 | 普通成员无任何角色时 Perms 必须为 []string{}(非 nil),JSON 序列化恒为 [](L-R18-3) | ✅ pass |
| TC-1207 | productmember.ErrNotFound 与 sqlx.ErrNotFound errors.Is 契约稳健性(M-R18-3) | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0529 | 冻结用户被403 | ✅ pass |
| TC-0530 | 用户不存在(Status=0) | ✅ pass |
| TC-0531 | UserDetails注入context | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0532 | createDept非超管拒绝 | ✅ pass |
| TC-0533 | updateDept非超管拒绝 | ✅ pass |
| TC-0534 | deleteDept非超管拒绝 | ✅ pass |
| TC-0535 | createProduct非超管拒绝 | ✅ pass |
| TC-0536 | updateProduct非超管拒绝 | ✅ pass |
| TC-0537 | createUser非产品管理员拒绝 | ✅ pass |
| TC-0538 | createRole非产品管理员拒绝 | ✅ pass |
| TC-0539 | updateRole非产品管理员拒绝 | ✅ pass |
| TC-0540 | deleteRole非产品管理员拒绝 | ✅ pass |
| TC-0541 | bindRolePerms非产品管理员拒绝 | ✅ pass |
| TC-0542 | updateUser-MEMBER不能管理他人 | ✅ pass |
| TC-0543 | updateUser自己修改DeptId被拒绝 | ✅ pass |
| TC-0544 | updateUser自己修改Status被拒绝 | ✅ pass |
| TC-0545 | updateUser未登录被拒绝 | ✅ pass |
| TC-0796 | LogoutHandler 无 userDetails ctx | ✅ pass |
| TC-0797 | LogoutHandler 携带合法 ctx | ✅ pass |
| TC-0798 | ChangePasswordHandler 非法 JSON body | ✅ pass |
| TC-0799 | ChangePasswordHandler 缺必填字段 | ✅ pass |
| TC-0800 | RefreshTokenHandler 缺 Authorization | ✅ pass |
| TC-0801 | RefreshTokenHandler 非法 bearer | ✅ pass |
| TC编号 | 测试场景 | 测试结果 |
|---|---|---|
| TC-0546 | 正常请求(未超限) | ✅ pass |
| TC-0547 | 超限请求被拒绝 | ✅ pass |
| TC-0548 | behindProxy=false时XFF被忽略 | ✅ pass |
| TC-0549 | behindProxy=false时X-Real-IP被忽略 | ✅ pass |
| TC-0550 | IP从RemoteAddr解析 | ✅ pass |
| TC-0551 | 不同IP独立限流 | ✅ pass |
| TC-0552 | behindProxy=true时信任X-Real-IP | ✅ pass |
| TC-0553 | behindProxy=true时无X-Real-IP回退RemoteAddr | ✅ pass |
| TC-0555 | RemoteAddr无端口格式 | ✅ pass |
| TC-0739 | quota=2 的 limiter,第 3 次 logout | ✅ pass |
| TC-0740 | 限流按 userId 隔离 | ✅ pass |
| TC-0741 | quota=1 limiter,burst 第 2 次 | ✅ pass |
| TC-0742 | 限流按 userId 隔离(productCode 无关) | ✅ pass |
| TC-0790 | period=1s quota=1, 打满后 sleep 1.2s 再调 | ✅ pass |
| TC-0791 | Redis 不可达(127.0.0.1:1 + NonBlock) |
✅ pass |
| TC-0862 | behindProxy=true + X-Forwarded-For: 1.1.1.1, 2.2.2.2 |
✅ pass |
| TC-0863 | behindProxy=true + X-Forwarded-For 全非法 + X-Real-IP: 10.0.0.1 |
✅ pass |
| TC-0864 | behindProxy=true + 两头均空 | ✅ pass |
| TC-0865 | behindProxy=true + X-Forwarded-For: " 3.3.3.3 " (空白) |
✅ pass |
| TC-0866 | behindProxy=false + XFF=1.1.1.1 |
✅ pass |
t.Run 子用例)1241;通过 1240,跳过 1,失败 0。./internal/logic/... 语句覆盖率 86.9%;整包连跑均绿,无并发 flake 触发。