| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- // academic 31xx 业务错误码单测(纯断言,不连库)。
- //
- // 覆盖 AC-02 验收②:31xx 码全落 3100~3199 段、无重复、文案非空、
- // 且与 infra/errors 通用码段(1xxx/2xxx/3xxx/5xxx)不重叠。
- package apperr
- import "testing"
- // TestCodesInAcademicRange 断言全部业务码落在 3100~3199 且唯一。
- func TestCodesInAcademicRange(t *testing.T) {
- allCodes := All()
- if len(allCodes) == 0 {
- t.Fatal("apperr.All() 不应为空")
- }
- seen := make(map[int]string, len(allCodes))
- for _, e := range allCodes {
- if e == nil {
- t.Fatal("apperr.All() 含 nil")
- }
- if !IsAcademicCode(e.Code) {
- t.Fatalf("错误码 %d(%s)越出 academic 段位 3100~3199", e.Code, e.Msg)
- }
- if prev, dup := seen[e.Code]; dup {
- t.Fatalf("错误码 %d 重复定义:%q 与 %q", e.Code, prev, e.Msg)
- }
- seen[e.Code] = e.Msg
- if e.Msg == "" {
- t.Fatalf("错误码 %d 文案为空(禁止无文案 sentinel)", e.Code)
- }
- }
- }
- // TestKnownCodes 逐条断言设计 §10.1 的码值(防误改错位,造成前端契约漂移)。
- func TestKnownCodes(t *testing.T) {
- pairs := []struct {
- name string
- got int
- want int
- }{
- {"3101 余额不足", ErrBalanceInsufficient.Code, 3101},
- {"3102 余额为0不可退费", ErrNoBalanceToRefund.Code, 3102},
- {"3103 可退金额不足(warn)", ErrRefundableShort.Code, 3103},
- {"3104 校区不存在", ErrCampusNotFound.Code, 3104},
- {"3105 已报名", ErrActivityAlreadySigned.Code, 3105},
- {"3106 老带新限一次", ErrRecommendLimited.Code, 3106},
- {"3107 已审核不可取消", ErrActivitySignedAudited.Code, 3107},
- {"3108 老带新已消费", ErrRecommendUsed.Code, 3108},
- {"3109 赠送金额不足", ErrGiftAmountShort.Code, 3109},
- {"3110 活动不可用", ErrActivityUnavailable.Code, 3110},
- {"3111 分账额度超限", ErrDivideQuotaExceeded.Code, 3111},
- {"3112 课酬方案未配置", ErrPayrollPlanMissing.Code, 3112},
- {"3113 欠费核销失败", ErrArrearsCounteractFailed.Code, 3113},
- {"3114 幂等重复(内部)", ErrRepeated.Code, 3114},
- {"3120 清零前置不满足", ErrClearBalanceRejected.Code, 3120},
- {"3121 上课状态非法", ErrRecordStateInvalid.Code, 3121},
- {"3122 排班冲突", ErrScheduleConflict.Code, 3122},
- {"3140 业务参数错", ErrBusinessParam.Code, 3140},
- {"3141 报名人数已满", ErrActivityFull.Code, 3141},
- }
- for _, p := range pairs {
- if p.got != p.want {
- t.Fatalf("%s:code = %d,期望 %d", p.name, p.got, p.want)
- }
- }
- if len(All()) != len(pairs) {
- t.Fatalf("All() 数量 = %d,期望 %d(新增码须同步本测试与设计 §10.1)", len(All()), len(pairs))
- }
- }
- // TestAllReturnsCopy All() 返回新切片(调用方 append 不得污染内部全集)。
- func TestAllReturnsCopy(t *testing.T) {
- a := All()
- a = append(a, ErrBalanceInsufficient)
- if len(All()) != len(a)-1 {
- t.Fatal("All() 未返回新切片:内部集合被调用方污染")
- }
- }
- // TestIsAcademicCode 段位边界(含端点/邻接非法值)。
- func TestIsAcademicCode(t *testing.T) {
- cases := []struct {
- code int
- want bool
- }{
- {3099, false},
- {3100, true},
- {3199, true},
- {3200, false},
- {1004, false},
- {2001, false},
- }
- for _, tc := range cases {
- if got := IsAcademicCode(tc.code); got != tc.want {
- t.Fatalf("IsAcademicCode(%d) = %v,期望 %v", tc.code, got, tc.want)
- }
- }
- }
|