test(push): 补 pi 建议的那一格 —— DailyLimit=1 时失败后仍要能发
上一提交补的是**内部计数器**(dayCount == 0)。pi 在报告里建议的是
**用户看得见的行为**:DailyLimit=1,一次 accessToken 失败后第二次
仍然要能发出去。
两层都要钉的理由:计数器对而行为错是可能的 —— 那会让运维收到
「达到每日推送上限」这种**误导性文案**,真实原因却是上一次网络抖动。
变异验证:把 reserveDaily 挪回 accessToken 之前 ⇒ 两格同时红。
--- FAIL: TestHMSAccessTokenFailureDoesNotBurnQuota
--- FAIL: TestHMSQuotaSurvivesTokenFailureWithLimitOne
This commit is contained in:
@ -701,3 +701,38 @@ func TestHMSAccessTokenFailureDoesNotBurnQuota(t *testing.T) {
|
||||
t.Fatalf("成功这一次应恰好计 1 条,实际 %d", used)
|
||||
}
|
||||
}
|
||||
|
||||
// TestHMSQuotaSurvivesTokenFailureWithLimitOne 用 pi 建议的形状再钉一遍:
|
||||
// `DailyLimit=1` 时,一次 accessToken 失败之后**第二次仍然要能发出去**。
|
||||
//
|
||||
// 为什么单独一格而不是并进上面那格:上面断言的是内部计数器(dayCount),
|
||||
// 这格断言的是**用户看得见的行为** —— 失败后收到的下一个错误不能是
|
||||
// 「达到每日推送上限」这种误导性文案(它会让运维以为配额用完了,
|
||||
// 而真实原因是上一次网络抖动)。计数器对、行为错是可能的,
|
||||
// 所以两层都要钉。
|
||||
func TestHMSQuotaSurvivesTokenFailureWithLimitOne(t *testing.T) {
|
||||
s := newHMSStub(t)
|
||||
h := s.hms()
|
||||
h.DailyLimit = 1
|
||||
|
||||
s.mu.Lock()
|
||||
s.failToken = true
|
||||
s.mu.Unlock()
|
||||
err1 := h.Send(context.Background(), []string{"tok-1"}, NewMail{MailID: "m1"})
|
||||
if err1 == nil {
|
||||
t.Fatal("accessToken 失败时必须返回错误")
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
s.failToken = false
|
||||
s.mu.Unlock()
|
||||
err2 := h.Send(context.Background(), []string{"tok-2"}, NewMail{MailID: "m2"})
|
||||
|
||||
if err2 != nil {
|
||||
if strings.Contains(err2.Error(), "上限") {
|
||||
t.Fatalf("★ 第二次被当成配额用尽拒绝(%v)—— 那次失败烧掉了当日配额,"+
|
||||
"而用户看到的文案会指向错误的原因", err2)
|
||||
}
|
||||
t.Fatalf("恢复正常后第二次必须发出去,实际: %v", err2)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user