rate_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. // Copyright 2015 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package rate
  5. import (
  6. "math"
  7. "runtime"
  8. "sync"
  9. "sync/atomic"
  10. "testing"
  11. "time"
  12. "golang.org/x/net/context"
  13. )
  14. func TestLimit(t *testing.T) {
  15. if Limit(10) == Inf {
  16. t.Errorf("Limit(10) == Inf should be false")
  17. }
  18. }
  19. func closeEnough(a, b Limit) bool {
  20. return (math.Abs(float64(a)/float64(b)) - 1.0) < 1e-9
  21. }
  22. func TestEvery(t *testing.T) {
  23. cases := []struct {
  24. interval time.Duration
  25. lim Limit
  26. }{
  27. {0, Inf},
  28. {-1, Inf},
  29. {1 * time.Nanosecond, Limit(1e9)},
  30. {1 * time.Microsecond, Limit(1e6)},
  31. {1 * time.Millisecond, Limit(1e3)},
  32. {10 * time.Millisecond, Limit(100)},
  33. {100 * time.Millisecond, Limit(10)},
  34. {1 * time.Second, Limit(1)},
  35. {2 * time.Second, Limit(0.5)},
  36. {time.Duration(2.5 * float64(time.Second)), Limit(0.4)},
  37. {4 * time.Second, Limit(0.25)},
  38. {10 * time.Second, Limit(0.1)},
  39. {time.Duration(math.MaxInt64), Limit(1e9 / float64(math.MaxInt64))},
  40. }
  41. for _, tc := range cases {
  42. lim := Every(tc.interval)
  43. if !closeEnough(lim, tc.lim) {
  44. t.Errorf("Every(%v) = %v want %v", tc.interval, lim, tc.lim)
  45. }
  46. }
  47. }
  48. const (
  49. d = 100 * time.Millisecond
  50. )
  51. var (
  52. t0 = time.Now()
  53. t1 = t0.Add(time.Duration(1) * d)
  54. t2 = t0.Add(time.Duration(2) * d)
  55. t3 = t0.Add(time.Duration(3) * d)
  56. t4 = t0.Add(time.Duration(4) * d)
  57. t5 = t0.Add(time.Duration(5) * d)
  58. t9 = t0.Add(time.Duration(9) * d)
  59. )
  60. type allow struct {
  61. t time.Time
  62. n int
  63. ok bool
  64. }
  65. func run(t *testing.T, lim *Limiter, allows []allow) {
  66. for i, allow := range allows {
  67. ok := lim.AllowN(allow.t, allow.n)
  68. if ok != allow.ok {
  69. t.Errorf("step %d: lim.AllowN(%v, %v) = %v want %v",
  70. i, allow.t, allow.n, ok, allow.ok)
  71. }
  72. }
  73. }
  74. func TestLimiterBurst1(t *testing.T) {
  75. run(t, NewLimiter(10, 1), []allow{
  76. {t0, 1, true},
  77. {t0, 1, false},
  78. {t0, 1, false},
  79. {t1, 1, true},
  80. {t1, 1, false},
  81. {t1, 1, false},
  82. {t2, 2, false}, // burst size is 1, so n=2 always fails
  83. {t2, 1, true},
  84. {t2, 1, false},
  85. })
  86. }
  87. func TestLimiterBurst3(t *testing.T) {
  88. run(t, NewLimiter(10, 3), []allow{
  89. {t0, 2, true},
  90. {t0, 2, false},
  91. {t0, 1, true},
  92. {t0, 1, false},
  93. {t1, 4, false},
  94. {t2, 1, true},
  95. {t3, 1, true},
  96. {t4, 1, true},
  97. {t4, 1, true},
  98. {t4, 1, false},
  99. {t4, 1, false},
  100. {t9, 3, true},
  101. {t9, 0, true},
  102. })
  103. }
  104. func TestLimiterJumpBackwards(t *testing.T) {
  105. run(t, NewLimiter(10, 3), []allow{
  106. {t1, 1, true}, // start at t1
  107. {t0, 1, true}, // jump back to t0, two tokens remain
  108. {t0, 1, true},
  109. {t0, 1, false},
  110. {t0, 1, false},
  111. {t1, 1, true}, // got a token
  112. {t1, 1, false},
  113. {t1, 1, false},
  114. {t2, 1, true}, // got another token
  115. {t2, 1, false},
  116. {t2, 1, false},
  117. })
  118. }
  119. func TestSimultaneousRequests(t *testing.T) {
  120. const (
  121. limit = 1
  122. burst = 5
  123. numRequests = 15
  124. )
  125. var (
  126. wg sync.WaitGroup
  127. numOK = uint32(0)
  128. )
  129. // Very slow replenishing bucket.
  130. lim := NewLimiter(limit, burst)
  131. // Tries to take a token, atomically updates the counter and decreases the wait
  132. // group counter.
  133. f := func() {
  134. defer wg.Done()
  135. if ok := lim.Allow(); ok {
  136. atomic.AddUint32(&numOK, 1)
  137. }
  138. }
  139. wg.Add(numRequests)
  140. for i := 0; i < numRequests; i++ {
  141. go f()
  142. }
  143. wg.Wait()
  144. if numOK != burst {
  145. t.Errorf("numOK = %d, want %d", numOK, burst)
  146. }
  147. }
  148. func TestLongRunningQPS(t *testing.T) {
  149. if runtime.GOOS == "openbsd" {
  150. t.Skip("low resolution time.Sleep invalidates test (golang.org/issue/14183)")
  151. return
  152. }
  153. // The test runs for a few seconds executing many requests and then checks
  154. // that overall number of requests is reasonable.
  155. const (
  156. limit = 100
  157. burst = 100
  158. )
  159. var numOK = int32(0)
  160. lim := NewLimiter(limit, burst)
  161. var wg sync.WaitGroup
  162. f := func() {
  163. if ok := lim.Allow(); ok {
  164. atomic.AddInt32(&numOK, 1)
  165. }
  166. wg.Done()
  167. }
  168. start := time.Now()
  169. end := start.Add(5 * time.Second)
  170. for time.Now().Before(end) {
  171. wg.Add(1)
  172. go f()
  173. // This will still offer ~500 requests per second, but won't consume
  174. // outrageous amount of CPU.
  175. time.Sleep(2 * time.Millisecond)
  176. }
  177. wg.Wait()
  178. elapsed := time.Since(start)
  179. ideal := burst + (limit * float64(elapsed) / float64(time.Second))
  180. // We should never get more requests than allowed.
  181. if want := int32(ideal + 1); numOK > want {
  182. t.Errorf("numOK = %d, want %d (ideal %f)", numOK, want, ideal)
  183. }
  184. // We should get very close to the number of requests allowed.
  185. if want := int32(0.999 * ideal); numOK < want {
  186. t.Errorf("numOK = %d, want %d (ideal %f)", numOK, want, ideal)
  187. }
  188. }
  189. type request struct {
  190. t time.Time
  191. n int
  192. act time.Time
  193. ok bool
  194. }
  195. // dFromDuration converts a duration to a multiple of the global constant d
  196. func dFromDuration(dur time.Duration) int {
  197. // Adding a millisecond to be swallowed by the integer division
  198. // because we don't care about small inaccuracies
  199. return int((dur + time.Millisecond) / d)
  200. }
  201. // dSince returns multiples of d since t0
  202. func dSince(t time.Time) int {
  203. return dFromDuration(t.Sub(t0))
  204. }
  205. func runReserve(t *testing.T, lim *Limiter, req request) *Reservation {
  206. return runReserveMax(t, lim, req, InfDuration)
  207. }
  208. func runReserveMax(t *testing.T, lim *Limiter, req request, maxReserve time.Duration) *Reservation {
  209. r := lim.reserveN(req.t, req.n, maxReserve)
  210. if r.ok && (dSince(r.timeToAct) != dSince(req.act)) || r.ok != req.ok {
  211. t.Errorf("lim.reserveN(t%d, %v, %v) = (t%d, %v) want (t%d, %v)",
  212. dSince(req.t), req.n, maxReserve, dSince(r.timeToAct), r.ok, dSince(req.act), req.ok)
  213. }
  214. return &r
  215. }
  216. func TestSimpleReserve(t *testing.T) {
  217. lim := NewLimiter(10, 2)
  218. runReserve(t, lim, request{t0, 2, t0, true})
  219. runReserve(t, lim, request{t0, 2, t2, true})
  220. runReserve(t, lim, request{t3, 2, t4, true})
  221. }
  222. func TestMix(t *testing.T) {
  223. lim := NewLimiter(10, 2)
  224. runReserve(t, lim, request{t0, 3, t1, false}) // should return false because n > Burst
  225. runReserve(t, lim, request{t0, 2, t0, true})
  226. run(t, lim, []allow{{t1, 2, false}}) // not enought tokens - don't allow
  227. runReserve(t, lim, request{t1, 2, t2, true})
  228. run(t, lim, []allow{{t1, 1, false}}) // negative tokens - don't allow
  229. run(t, lim, []allow{{t3, 1, true}})
  230. }
  231. func TestCancelInvalid(t *testing.T) {
  232. lim := NewLimiter(10, 2)
  233. runReserve(t, lim, request{t0, 2, t0, true})
  234. r := runReserve(t, lim, request{t0, 3, t3, false})
  235. r.CancelAt(t0) // should have no effect
  236. runReserve(t, lim, request{t0, 2, t2, true}) // did not get extra tokens
  237. }
  238. func TestCancelLast(t *testing.T) {
  239. lim := NewLimiter(10, 2)
  240. runReserve(t, lim, request{t0, 2, t0, true})
  241. r := runReserve(t, lim, request{t0, 2, t2, true})
  242. r.CancelAt(t1) // got 2 tokens back
  243. runReserve(t, lim, request{t1, 2, t2, true})
  244. }
  245. func TestCancelTooLate(t *testing.T) {
  246. lim := NewLimiter(10, 2)
  247. runReserve(t, lim, request{t0, 2, t0, true})
  248. r := runReserve(t, lim, request{t0, 2, t2, true})
  249. r.CancelAt(t3) // too late to cancel - should have no effect
  250. runReserve(t, lim, request{t3, 2, t4, true})
  251. }
  252. func TestCancel0Tokens(t *testing.T) {
  253. lim := NewLimiter(10, 2)
  254. runReserve(t, lim, request{t0, 2, t0, true})
  255. r := runReserve(t, lim, request{t0, 1, t1, true})
  256. runReserve(t, lim, request{t0, 1, t2, true})
  257. r.CancelAt(t0) // got 0 tokens back
  258. runReserve(t, lim, request{t0, 1, t3, true})
  259. }
  260. func TestCancel1Token(t *testing.T) {
  261. lim := NewLimiter(10, 2)
  262. runReserve(t, lim, request{t0, 2, t0, true})
  263. r := runReserve(t, lim, request{t0, 2, t2, true})
  264. runReserve(t, lim, request{t0, 1, t3, true})
  265. r.CancelAt(t2) // got 1 token back
  266. runReserve(t, lim, request{t2, 2, t4, true})
  267. }
  268. func TestCancelMulti(t *testing.T) {
  269. lim := NewLimiter(10, 4)
  270. runReserve(t, lim, request{t0, 4, t0, true})
  271. rA := runReserve(t, lim, request{t0, 3, t3, true})
  272. runReserve(t, lim, request{t0, 1, t4, true})
  273. rC := runReserve(t, lim, request{t0, 1, t5, true})
  274. rC.CancelAt(t1) // get 1 token back
  275. rA.CancelAt(t1) // get 2 tokens back, as if C was never reserved
  276. runReserve(t, lim, request{t1, 3, t5, true})
  277. }
  278. func TestReserveJumpBack(t *testing.T) {
  279. lim := NewLimiter(10, 2)
  280. runReserve(t, lim, request{t1, 2, t1, true}) // start at t1
  281. runReserve(t, lim, request{t0, 1, t1, true}) // should violate Limit,Burst
  282. runReserve(t, lim, request{t2, 2, t3, true})
  283. }
  284. func TestReserveJumpBackCancel(t *testing.T) {
  285. lim := NewLimiter(10, 2)
  286. runReserve(t, lim, request{t1, 2, t1, true}) // start at t1
  287. r := runReserve(t, lim, request{t1, 2, t3, true})
  288. runReserve(t, lim, request{t1, 1, t4, true})
  289. r.CancelAt(t0) // cancel at t0, get 1 token back
  290. runReserve(t, lim, request{t1, 2, t4, true}) // should violate Limit,Burst
  291. }
  292. func TestReserveSetLimit(t *testing.T) {
  293. lim := NewLimiter(5, 2)
  294. runReserve(t, lim, request{t0, 2, t0, true})
  295. runReserve(t, lim, request{t0, 2, t4, true})
  296. lim.SetLimitAt(t2, 10)
  297. runReserve(t, lim, request{t2, 1, t4, true}) // violates Limit and Burst
  298. }
  299. func TestReserveSetLimitCancel(t *testing.T) {
  300. lim := NewLimiter(5, 2)
  301. runReserve(t, lim, request{t0, 2, t0, true})
  302. r := runReserve(t, lim, request{t0, 2, t4, true})
  303. lim.SetLimitAt(t2, 10)
  304. r.CancelAt(t2) // 2 tokens back
  305. runReserve(t, lim, request{t2, 2, t3, true})
  306. }
  307. func TestReserveMax(t *testing.T) {
  308. lim := NewLimiter(10, 2)
  309. maxT := d
  310. runReserveMax(t, lim, request{t0, 2, t0, true}, maxT)
  311. runReserveMax(t, lim, request{t0, 1, t1, true}, maxT) // reserve for close future
  312. runReserveMax(t, lim, request{t0, 1, t2, false}, maxT) // time to act too far in the future
  313. }
  314. type wait struct {
  315. name string
  316. ctx context.Context
  317. n int
  318. delay int // in multiples of d
  319. nilErr bool
  320. }
  321. func runWait(t *testing.T, lim *Limiter, w wait) {
  322. start := time.Now()
  323. err := lim.WaitN(w.ctx, w.n)
  324. delay := time.Now().Sub(start)
  325. if (w.nilErr && err != nil) || (!w.nilErr && err == nil) || w.delay != dFromDuration(delay) {
  326. errString := "<nil>"
  327. if !w.nilErr {
  328. errString = "<non-nil error>"
  329. }
  330. t.Errorf("lim.WaitN(%v, lim, %v) = %v with delay %v ; want %v with delay %v",
  331. w.name, w.n, err, delay, errString, d*time.Duration(w.delay))
  332. }
  333. }
  334. func TestWaitSimple(t *testing.T) {
  335. lim := NewLimiter(10, 3)
  336. ctx, cancel := context.WithCancel(context.Background())
  337. cancel()
  338. runWait(t, lim, wait{"already-cancelled", ctx, 1, 0, false})
  339. runWait(t, lim, wait{"n-gt-burst", context.Background(), 4, 0, false})
  340. runWait(t, lim, wait{"act-now", context.Background(), 2, 0, true})
  341. runWait(t, lim, wait{"act-later", context.Background(), 3, 2, true})
  342. }
  343. func TestWaitCancel(t *testing.T) {
  344. lim := NewLimiter(10, 3)
  345. ctx, cancel := context.WithCancel(context.Background())
  346. runWait(t, lim, wait{"act-now", ctx, 2, 0, true}) // after this lim.tokens = 1
  347. go func() {
  348. time.Sleep(d)
  349. cancel()
  350. }()
  351. runWait(t, lim, wait{"will-cancel", ctx, 3, 1, false})
  352. // should get 3 tokens back, and have lim.tokens = 2
  353. t.Logf("tokens:%v last:%v lastEvent:%v", lim.tokens, lim.last, lim.lastEvent)
  354. runWait(t, lim, wait{"act-now-after-cancel", context.Background(), 2, 0, true})
  355. }
  356. func TestWaitTimeout(t *testing.T) {
  357. lim := NewLimiter(10, 3)
  358. ctx, cancel := context.WithTimeout(context.Background(), d)
  359. defer cancel()
  360. runWait(t, lim, wait{"act-now", ctx, 2, 0, true})
  361. runWait(t, lim, wait{"w-timeout-err", ctx, 3, 0, false})
  362. }
  363. func BenchmarkAllowN(b *testing.B) {
  364. lim := NewLimiter(Every(1*time.Second), 1)
  365. now := time.Now()
  366. b.ReportAllocs()
  367. b.ResetTimer()
  368. b.RunParallel(func(pb *testing.PB) {
  369. for pb.Next() {
  370. lim.AllowN(now, 1)
  371. }
  372. })
  373. }