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)
|
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