feat(rate): 自 go-hua 迁入秒级带宽限速器
- 按秒配额补充令牌, Add 阻塞限速, 配合 conn 使用; 附测试、例程与 README
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
package rate
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestNewRateLimitConvert(t *testing.T) {
|
||||
// 10 Mbps = 10*1024*1024/8 = 1310720 字节/秒
|
||||
r := NewRate(10)
|
||||
if r.Limit != 1310720 {
|
||||
t.Errorf("Limit = %d, want 1310720", r.Limit)
|
||||
}
|
||||
if r.Surplus != 1310720 {
|
||||
t.Errorf("初始 Surplus = %d, want 1310720", r.Surplus)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetLimit(t *testing.T) {
|
||||
r := NewRate(10)
|
||||
r.SetLimit(0)
|
||||
if r.Limit != 0 {
|
||||
t.Errorf("SetLimit(0) 后 Limit = %d, want 0", r.Limit)
|
||||
}
|
||||
r.SetLimit(1)
|
||||
if r.Limit != 1*1024*1024/8 {
|
||||
t.Errorf("SetLimit(1) 后 Limit = %d, want %d", r.Limit, 1*1024*1024/8)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddWithoutLimit(t *testing.T) {
|
||||
r := NewRate(0) // 不限速
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
r.Add(1 << 20)
|
||||
close(done)
|
||||
}()
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(time.Second):
|
||||
t.Error("不限速时 Add 阻塞了")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddConsumeQuota(t *testing.T) {
|
||||
r := NewRate(1) // 1 Mbps = 131072 字节/秒
|
||||
r.Add(1000)
|
||||
if got := atomic.LoadInt32(&r.Surplus); got != 131072-1000 {
|
||||
t.Errorf("Add 后 Surplus = %d, want %d", got, 131072-1000)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStartStopReset(t *testing.T) {
|
||||
r := NewRate(1)
|
||||
r.Start()
|
||||
|
||||
r.Add(500)
|
||||
// 等待配额重置(每秒一次)
|
||||
time.Sleep(1100 * time.Millisecond)
|
||||
if got := atomic.LoadInt32(&r.Surplus); got != 131072 {
|
||||
t.Errorf("重置后 Surplus = %d, want 131072", got)
|
||||
}
|
||||
|
||||
// Stop 应正常返回(IsStop 通道已在 NewRate 中初始化)
|
||||
r.Stop()
|
||||
|
||||
// 重复 Stop 不应 panic:第二次发送时 proc 协程已退出,会阻塞,故放入独立协程
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
r.Stop()
|
||||
}()
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(time.Second):
|
||||
t.Log("proc 协程已退出,第二次 Stop 阻塞(属预期)")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user